Kombinieren Sie xargs -I mit sed

Kombinieren Sie xargs -I mit sed

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, sedund 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 -xder 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.shcp

Um zu verwenden xargs, würde die Verarbeitung jedes einzelnen Dateinamens mehr Prozesse erfordern als der einzelne erforderliche cpBefehl.

Es ist viel effizienter, den einen Aufruf von sed generieren zu lassenalleder Befehle, als für jeden Dateinamen einen neuen Prozess cpaufzurufen .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)')"

verwandte Informationen