Jak wymusić tylko ścieżki względne w wyjściu „znajdź”?

25

Próbuję utworzyć skrypt, który może kompresować pliki z pewnym rozszerzeniem w wielu katalogach do jednej tar-ball. Obecnie mam w pliku skryptu:

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

Gdzie $rootDirjest podstawowa ścieżka do wyszukiwania.

Jest to w porządku, chyba że ścieżki są bezwzględne w pliku tar. Wolałbym, aby ścieżki były względne $rootDir. Jak miałbym to zrobić?

Przykład prądu tar -tf docs.targdzie $rootDirjest /home/username/testwyprowadzany:

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

Co chcę, aby wynik był:

./subdir/test.doc
./second.doc
Shane
źródło

Odpowiedzi:

12

Jeśli uruchomisz findz żądanego katalogu głównego i nie określisz absolutnego punktu początkowego w findopcjach, wyświetli on względne ścieżki do tarwywoływanych poleceń. Tak jak:

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

Jeśli nie chcesz trwale zmieniać aktualnego katalogu roboczego i używasz bashlub podobnej powłoki, możesz to zrobić

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

zamiast.

Zauważ, że pushd / popd nie są obecne we wszystkich powłokach, więc sprawdź stronę man odpowiednio. Są obecne w bash, ale nie w podstawowej implementacji sh, więc podczas jawnego używania /bin/bashmożesz na nich polegać, nie możesz tego zrobić, jeśli skrypt o to poprosi /bin/sh(ponieważ może to odwzorować na mniejszą powłokę, która nie ma ulepszeń bash)

David Spillett
źródło
Dzięki. Działa świetnie. Nie zdawałem sobie sprawy, że Linux miał pushd / popd.
Shane,
3
Lub po prostu użyj cd $rootDiri cd - (przynajmniej w bash). ( cd $rootDir ; find ... )byłoby również możliwe, tj. robienie wszystkiego w podpowłoce.
Daniel Beck
9

Możesz użyć %Pformatu z -printfdyrektywy:

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

wyświetli się w twoim przykładzie:

subdir/test.doc
second.doc

Następnie możesz użyć tej findlisty w forwyrażeniu, aby uruchomić nasze polecenie exec, jak w:

for f in $( find ${rootDir} -name '*.doc' -printf "%P\n" );
do
    tar rvf docs.tar ${f}
done
Gabriel
źródło
1
Przyjęte rozwiązanie działa, ale w zasadzie jest hackowaniem. IMHO powinno to być właściwe rozwiązanie tego pytania.
Narcolessico,
Dzięki Narcolessico. To także MHO :-)
Gabriel,