Ошибка из-за команды cp
, поэтому цитирование $directory
, хотя в целом хорошая идея, не поможет вам решить эту проблему.
Ваша конструкция будет терпеть неудачу с именами файлов/каталогов, которые содержат пробелы, случаи, когда grep получается с нулевыми совпадениями, и, возможно, другие случаи, о которых я не могу сейчас думать.
Некоторые лучшие решения:
Использовать имя find
«s соответствие вместо grep
и использовать -exec
с ним:
find "$directory" -type f \(-name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.cxx' \) -exec cp '{}' ~/src ';'
find "$directory" -type f -regextype posix-egrep -iregex '.*\.(c|cc|cpp|cxx)$' -exec cp '{}' ~/src ';'
Использование xargs
с \0
сепараторов вместо \n
:
find "$directory" -type f -print0 | grep -z -iE '\.(c|cc|cpp|cxx)$' | xargs -0 -I{} cp "{}" ~/src
Если файловая структура не является плоской (без подкаталогов), просто используйте cp
:
cd "$directory"; cp *.c *.cc *.cpp *.cxx ~/src
Ницца! В первом примере вы должны добавить круглые скобки вокруг части '-name .. -o -name ..', так как' -o' имеет более низкий приоритет, чем неявный '-a' перед' -exec'. Во втором примере вы можете дополнительно удалить проблему с линией, используя 'find -print0' и' grep -z'. Для третьего вы можете «shopt-globstar nullglob;», а затем использовать '**/*. {C, cc, cpp, cxx}', чтобы перейти рекурсивно и/или избавиться от ошибок, если не будет .cxx, только файлы .cpp. –
Ваш второй пример был бы лучше: 'find '$ directory" -type f -iregex'. * \. (C | cc | cpp | cxx) $ '-print0 | xargs -0 ... ' –
Отличные предложения, спасибо! Я отредактировал ответ. –