Моя текущая лучшая ставка:
for i in $(find . -name *.jpg); do echo $i; done
Проблема: не обрабатывает пробелы в именах файлов.
Примечание: я также хотел бы графического способа сделать это, например, команду "дерево".
Моя текущая лучшая ставка:
for i in $(find . -name *.jpg); do echo $i; done
Проблема: не обрабатывает пробелы в именах файлов.
Примечание: я также хотел бы графического способа сделать это, например, команду "дерево".
Ответы:
Канонический способ сделать
find . -name '*.jpg' -exec echo {} \;
(заменить \;
с , +
чтобы передать более одного файла echo
в то время)
или (специфично для GNU, хотя некоторые BSD теперь также имеют его):
find . -name '*.jpg' -print0 | xargs -r0 echo
ЗШ:
for i (**/*.jpg(D)) echo $i
echo
который расширяет escape-последовательности, такие как \b
(по крайней мере, соответствующие Unix echo
).
find
Manpage показано find . -type f -exec file '{}' \;
в EXAMPLES
разделе. Может быть, некоторые снаряды будут обрабатывать брекеты специально.
'{}'
, \{\}
, {}
, "{}"
, '{'}
разлагаются оболочкой (независимо от Борна типа оболочки) к одному аргументу , чтобы найти , что это два символа «{» и «}». Замените «find» на «echo find», или printf '<%s>\n' find
если вы хотите перепроверить.
Лучшие ответы уже были даны.
Но обратите внимание, что пробелы - не единственная проблема в коде, который вы дали. Символы табуляции, перевода строки и подстановочных знаков также являются проблемой.
С
IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done
Тогда только символы новой строки являются проблемой.
То, что вы упомянули, является одной из основных проблем, с которыми сталкиваются люди, когда они пытаются прочитать имена файлов. Иногда люди с ограниченными знаниями и неправильным представлением о структуре файлов и папок, как правило, забывают, что « в UNIX все является файлом ». Поэтому они не понимают, что им также нужно обрабатывать пробелы, поскольку имя файла может состоять из 2 или более слов с пробелами.
Решение. Таким образом, один из наиболее известных способов сделать это - сделать чистое чтение .
Здесь мы прочтем все имеющиеся файлы и сохраним их в переменной, в следующий раз, когда мы будем выполнять требуемую обработку, нам просто нужно будет сохранить эту переменную внутри кавычек, которая сохранит имена файлов с пробелами. Это один из основных способов сделать это, однако, другие ответы, предоставленные другими людьми здесь, работают так же хорошо.
СЦЕНАРИЙ:
find /path/to/files/ -iname "*jpg" | \
while read I; do
cp -v --parent "$I" /backup/dir/
done
Здесь я читаю файлы, задавая им путь, и, что бы я ни читал, я храню их в переменной I, которую я процитирую позже при обработке, чтобы сохранить пробелы для правильной обработки.
Надеюсь, это поможет вам в некотором роде.
Просто с find
и bash
:
find . -name '*.jpg' -exec bash -c '
echo "treating file $1 in bash, from path : ${1%/*}"
' -- {} \;
Таким образом, мы используем $1
в bash, как и в базовом скрипте, которые открывают хорошие перспективы для выполнения любых сложных (или нет) задач.
Более эффективный способ (чтобы избежать необходимости запуска нового bash для каждого файла):
find . -name '*.jpg' -exec bash -c 'for i do
echo "treating file $i in bash, from path : ${i%/*}"
done' -- {} +
В последней версии bash вы можете использовать globstar
опцию:
shopt -s globstar
for file in **/*.jpg ; do
echo "$file"
done
Для простых действий вы можете даже полностью пропустить цикл:
echo **/*.jpg
set -G
), его не следует использовать в bash, поскольку версия bash принципиально сломана (как GNU grep -r
), так как она спускается в символические ссылки на каталоги (эквивалентные find -L
или zsh). ***/*.jpg
). Также обратите внимание, что, в отличие от поиска, он пропускает точечные файлы и не спускается в точечные (по умолчанию).
$i
? Я делаю это, и это прекрасно работает. Что-то не так с этим подходом?