Wie kann ich in der Ausgabe "find" nur relative Pfade erzwingen?

25

Ich versuche, ein Skript zu erstellen, das Dateien mit einer bestimmten Erweiterung in einer Reihe von Verzeichnissen in eine einzige Zielgruppe komprimieren kann. Derzeit habe ich in der Skriptdatei Folgendes:

find "$rootDir" -name '*doc' -exec tar rvf docs.tar {} \;

Wo $rootDirist der Basispfad für die Suche?

Dies ist in Ordnung, außer dass die Pfade in der TAR-Datei absolut sind. Ich würde es vorziehen, wenn die Pfade relativ sind $rootDir. Wie würde ich das machen?

Beispiel Strom , tar -tf docs.tarwo $rootDirist /home/username/testoutput:

home/username/test/subdir/test.doc
home/username/test/second.doc

Was ich mir von der Ausgabe wünsche:

./subdir/test.doc
./second.doc
Shane
quelle

Antworten:

12

Wenn Sie findvom gewünschten Stammverzeichnis ausführen und keinen absoluten Startpunkt in findden Optionen angeben , werden relative Pfade zu den von ihm erstellten tarBefehlsaufrufen ausgegeben . Wie so:

cd $rootDir
find . -name '*doc' -exec tar rvf docs.tar {} \;

Wenn Sie das aktuelle Arbeitsverzeichnis nicht dauerhaft ändern möchten und bashals Shell oder ähnliches verwenden, können Sie dies tun

pushd $rootDir
find . -name '*doc' -exec tar rvf docs.tar {} \;
popd

stattdessen.

Beachten Sie, dass pushd / popd nicht in allen Shells vorhanden ist. Überprüfen Sie daher die entsprechende Manpage. Sie sind in bash, aber nicht in der base sh-Implementierung enthalten. /bin/bashWenn Sie sie also explizit verwenden , können Sie sich auf sie verlassen, wenn Sie von einem Skript /bin/shdazu aufgefordert werden.

David Spillett
quelle
Vielen Dank. Hat hervorragend funktioniert. Wusste nicht, dass Linux Pushd / Popd hat.
Shane
3
Oder benutze einfach cd $rootDirund cd - (zumindest in bash). ( cd $rootDir ; find ... )wäre auch möglich, also alles in einer Subshell zu machen.
Daniel Beck
9

Sie können das %PFormat in der -printfDirektive verwenden:

find ${rootDir} -name '*.doc' -printf "%P\n"

In Ihrem Beispiel wird Folgendes angezeigt:

subdir/test.doc
second.doc

Sie können diese findListe dann in einem forAusdruck verwenden, um unseren exec-Befehl auszuführen, wie in:

for f in $( find ${rootDir} -name '*.doc' -printf "%P\n" );
do
    tar rvf docs.tar ${f}
done
Gabriel
quelle
1
Die akzeptierte Lösung funktioniert, ist aber im Grunde genommen ein Hack. IMHO sollte dies die richtige Lösung für die Frage sein.
Narcolessico
Danke Narcolessico. Es ist auch MHO :-)
Gabriel