Действительно ли возможно получить статическую обратную ссылку с grep?

Обычно плохая идея разбирать выходные данные ls или find, потому что нельзя различить, какие символы являются частью имени файла, а какие - разделителями. Если вы не контролируете имена файлов, это может быть дырой в безопасности, позволяющей противнику создавать имена файлов, которые приводят к выполнению сценарием произвольного кода. Смотрите Почему мой скрипт оболочки давится пробелами или другими специальными символами?. Однако, в вашем случае это может быть нормально, тем более, что ваши файлы выглядят как некое дерево исходного кода, где часто встречаются имена файлов без "экзотических" символов, в частности, без пробелов.

Тем не менее, на самом деле не сложнее использовать надежную команду. Основная идея заключается в том, чтобы заставить find вызывать mv вместо разбора вывода find. Следующая команда рекурсивно перемещает .xml из текущей директории и подкаталогов:

find . ! -type d -name '*.xml' ! -name deposit.xml -exec mv {} ./Archive \;

Чтобы немного ускорить процесс, можно сгруппировать вызовы mv, запустив промежуточный оболочку.

find . ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

Если вы собирались перемещать только файлы из текущей директории, без обхода подкаталогов, то вы должны инструктировать find не рекурсивно:

find . ! -type d -name '*.xml' ! -name deposit.xml -exec mv {} ./Archive \;

для этого нужно сгруппировать вызовы mv. Если ваша реализация find поддерживает опцию -maxdepth:

find . -maxdepth 1 ! -type d -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

Иначе:

find . -name . -o -type d -prune -o -name '*.xml' ! -name deposit.xml -exec sh -c 'mv "$@" "$0"' ./Archive {} +

Если ваша оболочка - это ksh, вы можете использовать ее расширенные глобусы. Это проще, чем использовать find, но менее переносимо. Для перемещения файлов в текущем каталоге:

mv !(deposit).xml Archive/

В ksh93, для перемещения файлов из подкаталогов также:

set -o globstar
mv **/!(deposit).xml Archive/

В bash вы можете использовать шаблон !(...), но сначала вам нужно запустить shopt -s extglob. Чтобы использовать шаблон **/, вам нужно сначала запустить shopt -s globstar и остерегаться, что до bash 4.2, **/ в дополнение к каталогам будет осуществляться переход по символическим ссылкам на каталоги.

shopt -s extglob globstar
mv **/!(deposit).xml Archive/

В zsh можно использовать шаблон !(...) после выполнения setopt ksh_glob. В качестве альтернативы можно использовать синтаксис zsh после выполнения setopt extended_glob. Синтаксис рекурсивного обратного пути доступен в любом случае.

setopt extglob
mv **/(^deposit).xml Archive/

-1
27.03.2015, 22:21
1 ответ

Хорошо, думаю, я понял.  Ваш Источник: (?.*/).*\n regex захватывает, в группе , все после Источника:  до последнего / на линии.  Таким образом, для вашего примера, он захватывает /диск/средства массовой информации/камеру/.  Чтобы запечатлеть имя файла изображения JPEG, вам нужно

Source: .*/(?<group>.*)\n…

OK, ну вот опять.  Я полагаю, что вы / получаете нужную вам статическую обратную ссылку.  Проблема в том, что вы не получаете обратную ссылку. которые, как ты думаешь, ты получаешь.  Я думаю, что ваша группа захвата (и последующая обратная ссылка) всего лишь /.  Я не понимаю, почему это случилось, за исключением того, чтобы сделать дикое предположение, что .* работает в не жадном режиме, поэтому .*/ перехватывает все через первый /.  Может быть, ? каким-то образом интерпретируется как означающее это.

Я полагаю, что то, что вы хотите, может быть

Source: (?<group>.*/)[^/]*\n…

, что заставляет .*/ захватить все через последнее /.

1
28.01.2020, 05:11

Теги

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