Verwenden Sie "find" anstelle von "for - do - done", um auch Unterverzeichnisse zu durchsuchen

444
X-File

In OS X 10.8 habe ich ein paar Ordner mit Bildern, aber nicht alle Dateien haben die richtige Erweiterung, es gibt GIFs mit dem Namen JPG usw.

Ich habe einen Einzeiler, der die Arbeit für das aktuelle Verzeichnis erledigt:

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

Jetzt möchte ich stattdessen "find" verwenden, um auch die Unterordner zu durchsuchen, aber ich scheitere immer.

Irgendwelche Hinweise?

1
Ich sollte klarer sein: Nicht "selbst finden" ist mein Problem, sondern die korrekte Benennung am Ende, wenn ich das "{}" aus dem find-Befehl anstelle des "$ f" aus der for-Schleife verwenden muss. Entschuldigung, dass ich in meiner Frage nicht genau bin. X-File vor 7 Jahren 0
Hinweis für das nächste Mal: ​​Sie sollten diese Kommentare stattdessen unter Brunos Antwort gepostet haben. Wenn sie unter Ihrer Frage stehen, wird niemand darüber informiert. slhck vor 7 Jahren 0

4 Antworten auf die Frage

0
Bruno9779

In diesem Fall können Sie leicht Dateien finden, die nicht mit der Erweiterung .jpg übereinstimmen:

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

Sie können auch die Ergebnisse durchlaufen und prüfen, ob die Dateien tatsächlich jpg sind:

find . -type f -not "*.jpg" | while read fname; do if [[ $(file $fname) == *"JPG"*]] then echo $fname fi done 
Sie möchten `find… -print0 | verwenden während IFS = read -r -d '' fname` ist, siehe auch http://mywiki.wooledge.org/ParsingLs slhck vor 7 Jahren 0
Tnx Bruno, "while read" ist eine großartige Möglichkeit, dieses Problem auf die gleiche Weise zu lösen wie die "for do done" - Arbeit. Und wenn meine Frage nur nach einer pragmatischen Lösung gefragt würde, dann bin ich bei Ihnen ;-) Aber ich möchte wirklich wissen, wie dies mit `find` geparst werden könnte. X-File vor 7 Jahren 0
Ich analysiere mit "find" und wende die Ergebnisse mit etwas anderem ab ("while", "for", was auch immer). In Ihrer Lösung rufen Sie find für jeden von 'ls' zurückgegebenen Dateinamen auf. Vielleicht meinten Sie -exec verwenden? Bruno9779 vor 7 Jahren 0
0
slhck

Das einfachste wäre, rekursives Globbing für Dateien zu aktivieren, zB in Bash:

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

Auf diese Weise vermeiden Sie, dass Sie die findAusgabe analysieren müssen . Das Problem ist, dass bei zu vielen Dateien dieser Befehl fehlschlagen kann, da er möglicherweise die maximale Größe einer Befehlszeile überschreitet. Dies liegt daran, dass die Dateinamen in **/*.*Bash vor der Ausführung des Befehls erweitert werden.

Die Alternative ist also find, die Ausgabe zu whileund zu leiten read.

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

Einige bewährte Methoden für das Arbeiten mit Listen von Dateien finden Sie unter: http://mywiki.wooledge.org/ParsingLs

Ich habe nie daran gedacht! Tnx für diesen Hinweis! X-File vor 7 Jahren 0
0
X-File

Ich habe diesen Weg für mein Problem gefunden, aber es ist nicht wirklich elegant :-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

Ich denke, Sie suchen nach einer Möglichkeit, die Ergebnisse zu analysieren, ohne sie zu überlaufen, indem Sie nur find verwenden:

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

JA :-) Tnx, ich werde damit spielen. X-File vor 7 Jahren 0