Плагиат кода из ответа, на который вы ссылаетесь, и повышение его надежности:
for file in *; do mv "$file" "$(echo "$file" | tr '_' ' ')" ; done
Цитирование гарантирует, что каждое имя файла передается в mv
как единое
токен, а не разбивается на границах пространства.
Если у вас есть доступ к утилите переименования на основе Perl, следующая также будет работать:
rename -n 's/_/ /g' *
(Удалите переключатель -n
после подтверждения, что предварительный просмотр соответствует {{ 1}} на то, что вы хотели бы сделать.)
Не анализировать ls .
Вам не нужно xargs
для этого, вы можете использовать find -exec
.
попробуй это,
find. -maxdepth 1 -type f -name "*.html" -exec \
sh -c 'f=$(basename "$1"); echo "[${f%.*}]($1)" >> index.md' sh {} \;
Если вы хотите, чтобы использовал xargs
, используйте очень похожую версию:
find. -maxdepth 1 -type f -name "*.html" -print0 | \
xargs -0 -I{} sh -c 'f=$(basename "$1"); echo "[${f%.*}]($1)" >> index.md' sh {} \;
Другой способ без запуска xargs
или-exec
:
find. -maxdepth 1 -type f -name "*.html" -printf '[%f](./%f)\n' \
| sed 's/\.html\]/]/' \
> index.md
Просто сделай:
for f in *.html; do printf '%s\n' "[${f%.*}](./$f)"; done > index.md
Используйте set -o nullglob
(zsh
,yash
)илиshopt -s nullglob
(bash
)для *.html
, чтобы раскрыть ничего вместо*.html
(или сообщить об ошибке в zsh
), когда нет html
файла. С zsh
вы также можете использовать *.html(N)
или в ksh93
~(N)*.html
.
Или одним printf
звонком сzsh
:
files=(*.html)
rootnames=(${files:r})
printf '[%s](./%s)\n' ${basenames:^files} > index.md
Обратите внимание, что в зависимости от используемого синтаксиса уценки вам может потребоваться HTML -кодировать часть title , а URI -кодировать часть URI, если имена файлов содержат некоторые проблемные персонажи. Несоблюдение этого требования может даже привести к появлению формы уязвимости XSS в зависимости от контекста. с кш93,вы можете сделать это с помощью:
for f in *.html; do
title=${ printf %H "${file%.*}"; }
title=${title//$'\n'/"<br/>"}
uri=${ printf '%#H' "$file"; }
uri=${uri//$'\n'/%0A}
printf '%s\n' "[$title]($uri)"
done > index.md
Где %H
¹ определяет кодировку HTML, а %#H
кодировку URI, но нам по-прежнему нужно обращаться к символам новой строки отдельно.
Или сperl
:
perl -MURI::Encode=uri_encode -MHTML::Entities -CLSA -le '
for (<*.html>) {
$uri = uri_encode("./$_");
s/\.html\z//;
$_ = encode_entities $_;
s:\n:<br/>:g;
print "[$_]($uri)"
}'
Использование <br/>
для символов новой строки. Вместо этого вы можете использовать  или, в более общем случае, выбрать какую-либо форму альтернативного представления для непечатаемых символов -.
В вашем коде есть несколько ошибок:
ls
$
как литерал внутри двойных кавычек awk
для чего-то, что grep
может сделать (само по себе не неправильно, но излишне)xargs -0
, когда ввод не является NUL -разделителем -I
конфликтует с -L 1
. -L 1
запускает одну команду на строку ввода, но каждое слово в строке передается как отдельные аргументы, тогда как -I @@
запускает одну команду для каждой строки ввода с полной строкой (за вычетом завершающих пробелов и заключением в кавычки. все еще обрабатывается )используется для замены @@
. {}
внутри кода аргументаsh
(уязвимость внедрения команд)sh
var
в ${var%.*}
— это имя переменной , оно не будет работать с произвольным текстом. echo
для произвольных данных. Если вы хотите использовать xargs -0
, вам понадобится что-то вроде:
printf '%s\0' * | grep -z '\.html$' | xargs -r0 sh -c '
for file do
printf "%s\n" "[${file%.*}](./$file)"
done' sh > file.md
ls
на printf '%s\0' *
для получения вывода с разделителями NUL -awk
сgrep -z
(расширением GNU )для обработки этого вывода с разделителями NUL -xargs -r0
(Расширения GNU )без каких-либо -n
/ -L
/ -I
, потому что, пока мы создаем sh
, мы могли бы также обработать как можно больше файлов xargs
передать слова в качестве дополнительных аргументов в sh
(, которые становятся позиционными параметрами внутри встроенного кода ),не внутри аргумента кода. for file do
, который по умолчанию перебирает позиционные параметры ), поэтому мы можем использовать оператор раскрытия параметров ${param%pattern}
. printf
вместо echo
. Само собой разумеется, что нет особого смысла использовать это вместо того, чтобы выполнять этот цикл for
непосредственно над файлами *.html
, как в верхнем примере.
¹ Кажется, он не работает должным образом для многобайтовых символов в моей версии ksh93, хотя (ksh93u+ в системе GNU)
Вам действительно нужно xargs
?
ls *.html | perl -pe 's/.html\n//;$_="[$_](./$_.html)\n"'
(Если у вас более 100000 файлов):
printf "%s\n" *.html | perl -pe 's/.html\n//;$_="[$_](./$_.html)\n"'
или (медленнее, но короче):
for f in *.html; do echo "[${f%.*}](./$f)"; done