Как я могу заставить только относительные пути в «найти» вывод?

25

Я пытаюсь создать скрипт, который может сжимать файлы с определенным расширением в нескольких каталогах в один tar-шар. В настоящее время у меня есть в файле сценария:

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

Где $rootDirнаходится базовый путь для поиска.

Это нормально, за исключением того, что пути в файле tar являются абсолютными. Я бы предпочел, чтобы пути были относительно $rootDir. Как бы я поступил так?

Пример тока , tar -tf docs.tarгде $rootDirнаходится /home/username/testвыход:

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

Что я хочу, чтобы результат был:

./subdir/test.doc
./second.doc
Шейн
источник

Ответы:

12

Если вы запускаете findиз нужного корневого каталога и не указываете абсолютную начальную точку в findпараметрах, он выведет относительные пути к tarвызовам команд, которые он создает. Вот так:

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

Если вы не хотите постоянно менять текущий рабочий каталог и используете его bashили как-то похожее на вашу оболочку, вы можете сделать это

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

вместо.

Обратите внимание, что pushd / popd присутствуют не во всех оболочках, поэтому проверьте соответствующую страницу руководства. Они присутствуют в bash, но не в реализации base sh, поэтому при явном использовании /bin/bashвы можете на них положиться, но не сможете, если /bin/shвместо этого запросит скрипт (поскольку это может отображаться в меньшую оболочку, не имеющую улучшений bash)

Дэвид Спиллетт
источник
Благодарю. Работал блестяще. Не понял, что в Linux есть pushd / popd.
Шейн
3
Или просто использовать cd $rootDirи cd - (по крайней мере, в bash). ( cd $rootDir ; find ... )также было бы возможно, то есть делать все в подзаголовке.
Даниэль Бек
9

Вы можете использовать %Pформат в -printfдирективе:

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

будет отображаться в вашем примере:

subdir/test.doc
second.doc

Затем вы можете использовать этот findсписок в forвыражении для запуска нашей команды exec, например:

for f in $( find ${rootDir} -name '*.doc' -printf "%P\n" );
do
    tar rvf docs.tar ${f}
done
Габриель
источник
1
Принятое решение работает, но в основном это взломать. ИМХО это должно быть правильное решение вопроса.
Нарколессико
Спасибо Нарколессико. Это также MHO :-)
Габриэль