Я пытаюсь использовать find
команду для вывода списка размеров определенного набора файлов, но не получаю вывода. Команда, которую я использую, следующая:
find POD -type f -name *.mp3 -or -name *.ogg -ls
Который не производит никакого вывода. В то время как:
find POD -type f -name *.mp3 -or -name *.ogg
производит вывод, я также пробовал действия:
-printf "%p %k KB\n"
-exec ls -ls '{}' \;
-print0
но все это не дает никакого результата. Когда я использую любое из этих действий с другим выражением, например:
find . -maxdepth 1 -type f -printf "%p %k KB\n"
Я также получаю ожидаемый вывод. Кто-нибудь знает, в чем проблема? Я запускаю:
Linux irimi 3.10.37-1-MANJARO #1 SMP Mon Apr 14 20:56:29 UTC 2014 x86_64 GNU/Linux
aka современный дистрибутив Manjaro linux. Оболочка, которую я использую: /bin/bash
версия 4.3.8(1)-release
.
Содержимое моей SHELLOPTS
переменной среды:
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
Моя BASHOPTS
переменная окружения:
cdspell:checkwinsize:cmdhist:complete_fullquote:dotglob:expand_aliases:extglob:extquote:force_fignore:histappend:hostcomplete:interactive_comments:nocaseglob:progcomp:promptvars:sourcepath
Опять же, любая помощь в попытке отладки будет очень признательна.
решение1
Есть ловушка си/илиключевые слова на find
. or
применяются ко всем следующим параметрам, включая действие ( -ls
в вашем примере). and
выражения без or
(или присоединенные к and
) оцениваются в порядке чтения с конечной остановкой как ложь. Нет implicit ()
.
Итак, команда find POD -type f -name *.mp3 -or -name *.ogg -ls
означает:
- поиск (начиная с каталога POD) файлов --- если файл не найден: ОСТАНОВИТЬ
- в противном случае (файл найден) проверка соответствия шаблону
*.mp3
--- если соответствие шаблону: СТОП! (потому чтоOR
применяется отсюда и только в случае, если предыдущая команда не удалась (но только предыдущая команда, а не предыдущие группы команд)
и поскольку вы добавляете оператор выполнения ( -ls
, -exec
, -print
....) в командную строку, то неявной команды нет -print
, и поэтому нечего выполнять, если 1) все условия 1) истинны (файл и шаблон совпадают). Если вы удалите последний, то в конце каждого условия -ls
будет неявно распределено.-print
- в противном случае, если шаблон не совпал, выполняется поиск всего, что соответствует шаблону (файл/каталог),
*.ogg
и вывод их списка (-ls
команда не является условной, она выполняется только в том случае, если предыдущая команда/тест «шаблон»*.ogg
верна). Но из-за 1), 2) оценивается только для НЕ mp3-файлов. Если у вас нет.ogg
файлов, вы ничего не увидите.
Решение 1 повторить команду выполнения в каждой логической ветви
find POD -type f -name "*.mp3" -ls -or -name "*.ogg" -ls
Решение 2добавить (защищенную оболочкой) скобку
find POD -type f \( -name "*.mp3" -ls -or -name "*.ogg" \) -ls
Примечание вам следует защитить шаблоны, чтобы избежать оценки шаблонов оболочки в текущем каталоге.
решение2
Я думаю, это из-за порядка оценки (отсутствия явного приоритета), например, если
-name '*.mp3' -o -name '*.ogg' -ls
тогда если -name '*.ogg'
оценивается как ложь, ls
действие не выполняется. Вы можете получить ожидаемое поведение, сгруппировав выражения OR с помощью скобок - например, если
$ ls tests
file1.mp3 file2.mp3 file3.mp3
Затем
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
tests/file3.mp3
tests/file1.mp3
tests/file2.mp3
тогда как
$ find tests -name '*.mp3' -o -name '*.ogg' -print
не производит никакого вывода. Обратите внимание, что
$ find tests -name '*.mp3' -o -name '*.ogg'
является особым случаем, поскольку он неявно рассматривается как
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
Также обратите внимание, что хорошей практикой является заключение в кавычки или экранирование подстановок оболочки в find
команде, чтобы оболочка не могла их раскрыть — см. раздел NON-BUGS
на странице руководства find.