Ключевой фактор в достижении find
просветления;):
find
занимается оценкой выражений - не поиск файлов. Да,find
определенно находит файлы; но на самом деле это всего лишь побочный эффект.
Существует альтернативный подход к этому вопросу, о котором стоит знать (как также описано в Unix Power Tools, в разделе «Использование -exec для создания пользовательских тестов» ]):
find . -type f -exec sh -c 'file -b "$1" | grep -iqE "^ELF|^C source"' sh {} \; -print
Об этом методе фильтрации стоит знать, поскольку его можно использовать для многих других целей, чем просто вывод имени файла; просто замените оператор -print
на любой другой, который вам нравится (включая другой оператор -exec
), и делайте с ним все, что вам нравится.
Здесь есть недостаток производительности этой команды (который также присутствует в другом ответе ), поскольку мы используем \;
и не +
, мы создаем оболочку для каждого файла. Использование +
для одновременной передачи нескольких файлов команде sh
и их обработка с помощью цикла for
дает заметное преимущество в производительности:
find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} +
Вы можете увидеть сравните для себя, выполнив обе следующие команды и сравнив вывод time
:
time find . -exec sh -c 'for f do file -b "$f" | grep -qE "^ELF|^C source" && printf %s\\n "$f"; done' sh {} +
time find . -exec sh -c 'file -b "$1" | grep -qE "^ELF|^C source" && printf %s\\n "$1"' sh {} \;
Однако реальный момент таков:
Никогда не запускайте оболочку для цикла
на список файлов, выводимый из find
. Вместо этого выполните действие, которое необходимо выполнить для каждого файла непосредственно в find
с помощью оператора -exec
, либо вставьте оболочку ] for
цикл внутри команда find
и делает это таким же образом.
Некоторые дополнительные причины:
Все дело в использовании захваченных групп цифр и размещении групп в нужных местах для получения требуемого имени:
sed -E 's/^([[:digit:]]{4})([[:digit:]]{2})([[:digit:]]{2})-([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})__(\+[[:digit:]]+)/\7__\3-\2-\1_\4-\5-\6/'
-E
включает ERE (расширенные регулярные выражения)
[[:digit:]]
соответствует локали -знакомой цифре
{N}
соответствует N
номеру предыдущего токена, например. [[:digit:]]{2}
соответствует 2 цифрам; это также может быть диапазон, например. [[:digit:]]{2,4}
соответствует от 2 до 4 цифр Пример:
% sed -E 's/^([[:digit:]]{4})([[:digit:]]{2})([[:digit:]]{2})-([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2})__(\+[[:digit:]]+)/\7__\3-\2-\1_\4-\5-\6/' <<<'20190212-112007__+313206601234.amr'
+313206601234__12-02-2019_11-20-07.amr