Comment puis-je forcer uniquement les chemins relatifs dans la sortie "find"?

25

J'essaie de créer un script qui peut compresser des fichiers avec une certaine extension dans un certain nombre de répertoires en une seule tar-ball. Actuellement, ce que j'ai dans le fichier script est:

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

$rootDirest le chemin de base pour rechercher.

C'est très bien sauf que les chemins sont absolus dans le fichier tar. Je préférerais que les chemins soient relatifs $rootDir. Comment pourrais-je procéder?

Exemple de courant tar -tf docs.tar$rootDirest /home/username/testsorti:

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

Ce que je souhaite que la sortie soit:

./subdir/test.doc
./second.doc
Shane
la source

Réponses:

12

Si vous exécutez à findpartir du répertoire racine souhaité et ne spécifiez pas de point de départ absolu dans findles options de, il affichera des chemins relatifs vers les tarappels de commandes qu'il construit. Ainsi:

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

Si vous ne souhaitez pas modifier définitivement le répertoire de travail actuel et que vous utilisez bashou similaire à votre shell, vous pouvez le faire

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

au lieu.

Notez que pushd / popd ne sont pas présents dans tous les shells, vérifiez donc la page de manuel comme il convient. Ils sont présents dans bash mais pas dans l'implémentation de base sh, donc si /bin/bashvous les utilisez explicitement, vous ne pouvez pas vous y fier si un script le demande à la /bin/shplace (car cela peut correspondre à un plus petit shell qui n'a pas les améliorations de bash)

David Spillett
la source
Merci. Fonctionne avec brio. Je ne savais pas que Linux avait pushd / popd.
Shane
3
Ou utilisez simplement cd $rootDiret cd - (au moins dans bash). ( cd $rootDir ; find ... )serait également possible, c'est-à-dire tout faire en sous-couche.
Daniel Beck
9

Vous pouvez utiliser le %Pformat dans la -printfdirective:

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

s'affichera dans votre exemple:

subdir/test.doc
second.doc

Vous pouvez ensuite utiliser cette findliste dans une forexpression, afin d'exécuter notre commande exec, comme dans:

for f in $( find ${rootDir} -name '*.doc' -printf "%P\n" );
do
    tar rvf docs.tar ${f}
done
Gabriel
la source
1
La solution acceptée fonctionne mais est essentiellement un hack. À mon humble avis, cela devrait être la bonne solution à la question.
Narcolessico
Merci Narcolessico. C'est aussi MHO :-)
Gabriel