find: текущее имя файла оценивается как пустое в вложенная команда

Благодаря дружественному контакту в IRC я ​​нашел рабочее решение для удаления определенного каталога с помощью одной команды rsync .Он работает путем указания аргумента - include для содержимого каталога ( - include '/ 20150101000000 / **' ), отдельного - include ] для самого каталога ( - включить '/ 20150101000000 /' ) и - исключить '*' , чтобы игнорировать все остальное содержимое каталога верхнего уровня (в этом case, versions / ):

rsync -vr --delete --include '/20150101000000/**' --include '/20150101000000/' --exclude '*' `mktemp -d`/ rsync://user@host:123/module/versions/

Затем я углубился в страницу руководства, пытаясь полностью понять вышесказанное, и наткнулся на этот удобный раздел:

завершающий "dir_name / ***" "будет соответствовать как каталогу (как если бы было указано" dir_name / "), так и всему в каталоге (как если бы было указано" dir_name / ** "). Это поведение было добавлено в версии 2.6.7.

Эта информация позволяет нам упростить до одного - включить аргумент:

rsync -vr --delete --include '/20150101000000/***' --exclude '*' `mktemp -d`/ rsync://user@host:123/module/versions/
0
25.09.2017, 20:33
2 ответа

Используйте:

find. -type f -exec sh -c 'echo "$(identify -format %w-%h "$1")"' sh {} \;

Пояснение

Проблема заключается в том, как bash раскрывает переменные

find * -type f -exec echo "$(identify -format '%w-%h' {})" \;

Первый удар расширяет то, что находится внутри$(...):

find * -type f -exec echo 'identify: unable to open image `{}': No such file or directory...' \;

В этот момент find будет использовать один и тот же оператор exec для всех команд с довольно бесполезным аргументом. Что вы хотите сделать, так это подавить расширение bash внутри find exec. Вы можете остановить расширение bash, поместив их в одинарные кавычки

find * -type f -exec echo '$(identify -format %w-%h {})' \;

Но здесь мы полностью теряем расширение, мы можем ввести его обратно, запустив выражение сsh -c

find * -type f -exec sh -c 'echo "$(identify -format %w-%h {})"' \;

Наличие {}в сценарии оболочки также может привести к некоторым непредвиденным ошибкам при работе с пробелами, кавычками или любым символом, характерным для оболочки в именах файлов. Чтобы обойти это, вы должны переместить {}в качестве аргумента в sh с:

find * -type f -exec sh -c 'echo "$(identify -format %w-%h "$1")"' sh {} \;

См. этот вопрос/ответ для более подробного объяснения этого.

Наконец, вы можете заменить *на ., чтобы позволить findсамостоятельно находить файлы в текущем каталоге (и включать скрытые файлы, а также без сбоев для имен файлов, начинающихся с-).

Кроме того, вы можете добавить флаг -xк sh, чтобы распечатать то, что было выполнено, чтобы помочь с отладкой команды -, это может быть очень шумным для многих файлов.

1
28.01.2020, 02:24

Это потому, что echoне знает, что такое {}внутри себя, чтобы расширить его, только execпонимает {}, в этом случае вам следует использовать режим sh -c.

find. -type f -exec sh -c 'echo "$(identify -format '%w-%h' "$1")"' sh '{}' \;
2
28.01.2020, 02:24

Теги

Похожие вопросы