
Ich möchte find verwenden, um bestimmte Dateien zu finden und diese dann mit xargs mit cp und sed in einen anderen Ordner zu verschieben und umzubenennen. Ich weiß, wie man das in einer Schleife macht, aber das ist nicht das, wonach ich suche.
Ich habe es versucht:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
Warum funktioniert das nicht und was wäre eine Lösung?
Antwort1
Versuchen Sie dies. Es braucht nicht xargs
, nur find
, sed
und copy
. Es werden keine Dateien geändert, aberWilleDrucken Sie eine Liste von Shell-Befehlen zum Kopieren der Dateien. Wenn Ihnen die ausgegebenen Befehle gefallen, führen Sie das Programm erneut aus, entfernen Sie das #
vor sh -x
der letzten Zeile und lassen Sie die Shell die Befehle ausführen.
find "${FOLDER:-.}" -iname "*${SOME_STRING:-ABC}*" |
sed "
s/^/'/ # surround filename with single quotes
s/$/'/
h # save filename in the sed hold space
s/ABC/XYZ/g # change filename
H # append to hold space (separates with newline)
g # get original and modified from hold
s/\n/ /g # replace the newline with a space
s/^/cp -i/ # make it into a copy command
" #| sh -x # optionally pipe to shell
Warum ist dieser Ansatz in diesem Fall besser xargs
? Weil diese Methode zusätzlich zum erforderlichen Befehl für jede Datei nur insgesamt 3 Prozesse ( find
, sed
, und ) startet.sh
cp
Um zu verwenden xargs
, würde die Verarbeitung jedes einzelnen Dateinamens mehr Prozesse erfordern als der einzelne erforderliche cp
Befehl.
Es ist viel effizienter, den einen Aufruf von sed generieren zu lassenalleder Befehle, als für jeden Dateinamen einen neuen Prozess cp
aufzurufen .sed
Antwort2
Mit GNU Parallel sieht es folgendermaßen aus:
find ${FOLDER} -iname "*${SOME_STRING}*" |
parallel cp {} '{= s/ABC/XYZ/g =}'
Die {= =}-Konstruktion enthält einen Perl-Ausdruck, der $_ ändert.
Einer der Vorteile besteht darin, dass GNU Parallel das Richtige tut, selbst wenn Sie Dateien mit dem Namen haben:
My brother's 12" records worth >100$.txt
oder Schrecken wie:
touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"