Пакетное переименование, когда в целевом файле требуются пробелы

Вам необходимо использовать флаг p , чтобы установить другие флаги раскрытия (следуйте p ) распознать escape-последовательность:

$ printf '%s\n' ${(ps:\0:)VAR}
5
0
7

или использовать сокращение:

printf '%s\n' ${(0)VAR}

Чтобы сохранить пустые элементы:

printf '%s\n' "${(0@)VAR}"

, но вы не можете использовать это для вывода из find ... -print0 , потому что это добавлен завершающий \ 0 для вывода, вы всегда будете получать последний пустой элемент.

0
20.02.2019, 16:03
2 ответа

Просто добавьте кавычки вокруг имени цели:

 mv $i "$(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /')" ; 
0
28.01.2020, 02:30

Основная проблема заключается в том, что подстановка команды не заключена в кавычки, поэтому она разбивается на отдельные аргументы, и каждый аргумент подвергается расширению пути (, последняя часть в bash, но не zsh), и когда mvвидит более двух, предполагается, что последний является каталогом для перемещения файлов.

По той же причине само $iследует заключать в кавычки (в bash), и во избежание проблем, если какое-то имя файла начинается с тире -, следует использовать ./*вместо *в шаблоне или поставьте конец -из -маркера опций --в команде mv.

Кроме того, я думаю, мы могли бы немного упростить способ обработки имен файлов. Начнем с того, что sedможет принимать несколько команд, поэтому вам нужно вызвать его только один раз. Вы также, вероятно, захотите добавить /gв конец команд s///, чтобы сделать замены для всех совпадений, а не только для первого. Также обратите внимание, что 2 из этих 3 обратных слэшей в [_\?\!\]избыточны. Используйте [_?!], если вы хотите сопоставить _, ?или !или [_\?!], если вы также хотите включить обратную косую черту (, хотя [_\\?!]сделает его более надежным с некоторыми утилитами ).

for f in./*; do
    mv -- "$f" "$(grep \# "$f" | head -1 | sed -e 's/# //g' -e 's/[_?!]//g' -e's/[:/]/ - /g')"
done

Вы также можете объединить grepи headв sedтоже:

for f in./*; do
    mv -- "$f" "$(sed -ne '/^# / {s///; s/[_?!]//g; s/[:/]/ - /g; p; q;}' < "$f")"
done

Здесь команды внутри {}зависят от шаблона /^# /, а qв конце выходит из скрипта в конце этого блока,поэтому обрабатывается только первая совпадающая строка.

Аналогично вawk:

awk '/^# / { sub(/# /, ""); gsub(/[_?!]/, ""); gsub(/[:/]/, " - "); print; exit }' < "$f"

Я мог бы также изменить последнюю замену на s/[:/] */ - /, чтобы строка типа blah: blehпревратилась в blah - blahвместоblah - bleh(с двумя пробелами после дефиса ).

2
28.01.2020, 02:30

Теги

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