Используйте «find» вместо «for - do - done» для поиска в подкаталогах.

337
X-File

В OS X 10.8 у меня есть пара папок с изображениями, но не все файлы имеют правильное расширение, есть GIF-файлы с именем JPG и т. Д.

У меня есть одна строка, которая делает работу для фактического каталога:

for f in * ; do type=$(file "$f" | tr "[A-Z]" "[a-z]" | awk '') ; mv "$f" "$.$type" ; done 

Теперь я хотел бы использовать «поиск» вместо того, чтобы также искать подпапки, но я всегда терплю неудачу.

Есть намеки?

1
Я должен быть более ясным: проблема не в «самом поиске», а в правильном именовании в конце, когда мне нужно использовать «{}» из команды поиска вместо «$ f» из цикла for. Извините за то, что не отвечал точно на мой вопрос. X-File 7 лет назад 0
Примечание для следующего раза: Вы должны были опубликовать эти комментарии под ответом Бруно. Если они ниже вашего вопроса, никто не получит уведомление о них. slhck 7 лет назад 0

4 ответа на вопрос

0
Bruno9779

В этом случае вы можете легко найти файлы, НЕ соответствующие расширению .jpg:

find . -type f -not "*.jpg" 

Вы также можете просмотреть результаты и проверить, являются ли файлы на самом деле jpg:

find . -type f -not "*.jpg" | while read fname; do if [[ $(file $fname) == *"JPG"*]] then echo $fname fi done 
Вы хотите использовать `find… -print0 | тогда как IFS = read -r -d '' fname`, см. также http://mywiki.wooledge.org/ParsingLs slhck 7 лет назад 0
Tnx Bruno, `while read` - отличный способ решить эту проблему таким же образом, как и` for do done 'работа. И если бы мой вопрос был задан только для того, чтобы найти прагматичное решение, я с вами ;-) Но я действительно хочу знать, как это можно было бы проанализировать с помощью `find`. X-File 7 лет назад 0
Я анализирую с `find` и перебираю результаты с чем-то другим (` while`, `for`, что угодно). В вашем решении вы вызываете find для каждого имени файла, возвращаемого `ls`. Может быть, вы имели в виду использование -exec? Bruno9779 7 лет назад 0
0
slhck

Проще всего было бы включить рекурсивное сглаживание для файлов, например, в Bash:

shopt -s globstar for f in **/*.*; do type=$(file "$f" | tr "[A-Z]" "[a-z]" | awk '') mv -- "$f" "$.$type" done 

Таким образом, вам не придется анализировать findвывод. Проблема в том, что если файлов слишком много, эта команда может завершиться ошибкой, поскольку она может превысить максимальный размер командной строки. Это связано с тем, что имена файлов в **/*.*Bash будут расширены до выполнения команды.

Таким образом, альтернатива заключается в использовании find, передавая свой вывод в whileи read.

find . -type f -print0 | while IFS= read -r -d '' f type=$(file "$f" | tr "[A-Z]" "[a-z]" | awk '') mv -- "$f" "$.$type" done 

Некоторые рекомендации по работе со списками файлов см. По адресу : http://mywiki.wooledge.org/ParsingLs.

Я никогда не думал об этом! TNX для этой подсказки! X-File 7 лет назад 0
0
X-File

Я нашел этот способ для моего теста, но это не очень элегантно :-P

find . -type f -name "*.*" -exec sh -c 'name=$(basename {} | cut -d. -f1) ; type=$(file {} | tr "[A-Z]" "[a-z]" | cut -d" " -f2) ; mv `basename {}` "$name.$type"' \; 
0
Bruno9779

Из предыдущих комментариев, я думаю, вы ищете способ проанализировать результаты, не зацикливая их, используя только find:

find . -type f -not "*.jpg" -exec sh -c "if [[ $(file {}) == *'JPG'* ]] then; echo {}; fi" \;

ДА :-) TNX, я буду играть с этим. X-File 7 лет назад 0