Как передать имена каталогов текущего пути (с пробелами) в качестве аргументов сценарию bash? - PullRequest
1 голос
/ 24 апреля 2020

Я могу воспроизвести эту проблему как в Ubuntu bash, так и в Windows / Cygwin bash. Проблема возникает с именами файлов и каталогов, в которых есть пробелы. Вот мой скрипт под названием pass-dir-names-with-space. sh:

for dir in "$@"
do
  echo dir = $dir
done

Это прекрасно работает:

./pass-dir-names-with-spaces.sh *
dir = pass-file-names-with-spaces.sh
dir = this is a directory with spaces in it
dir = this is a file name with spaces.txt
dir = this is another file name with spaces.txt

Я получаю полное имя файла в каждой строке даже если в нем есть пробелы. Иногда это вполне приемлемо, потому что мне нужны имена файлов и каталогов. Однако иногда я хочу реализовать фильтр с perl для удаления имен файлов.

Подход backtick / perl не работает! Вот моя первая попытка избежать пробелов.

./pass-dir-names-with-spaces.sh `perl -e ' my @m  = (); my $c = shift @ARGV; opendir $h, $c or die "cannot opendir $c"; @a= map { push @m, $_ if  -d $_ } grep(!/^\.\.$/,readdir $h); closedir $h; foreach (@m){s/ /\\\\ /g; print " $_ " } '  .`
dir = .
dir = this\
dir = is\
dir = a\
dir = directory\
dir = with\
dir = spaces\
dir = in\
dir = it

Я попытался использовать вместо этого кавычки:

./pass-dir-names-with-spaces.sh `perl -e ' my @m  = (); my $c = shift @ARGV; opendir $h, $c or die "cannot opendir $c"; @a= map { push @m, $_ if  -d $_ } grep(!/^\.\.$/,readdir $h); closedir $h; foreach (@m){ print " \"$_\" " } '  .`
dir = "."
dir = "this
dir = is
dir = a
dir = directory
dir = with
dir = spaces
dir = in
dir = it"

Кажется, bash игнорирует мои кавычки! Кажется, что "$ @" ведет себя неправильно! Как я могу отфильтровать имена файлов?

Спасибо

Зигфрид

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Это способ передачи имен каталогов, который является неправильным.

Вам необходимо изменить структуру вызова следующим образом (упрощенная версия perl сценария):

readarray -t -d '' dirs < <(perl -e 'print "$_\x00"')
./pass-dir-names-with-spaces.sh "${dirs[@]}"
1 голос
/ 24 апреля 2020
  • set --: очистить массив аргументов.
  • for d in *; do: перебрать каждую запись каталога как переменную d.
  • [ -d "$d" ] && set -- "$@" "$d": если запись d является каталогом, добавьте его в массив arguments.
  • ./pass-dir-names-with-spaces.sh "$@": Наконец, передайте массив arguments в ваш скрипт или команду.
set --
for d in *; do
  [ -d "$d" ] && set -- "$@" "$d"
done
./pass-dir-names-with-spaces.sh "$@"

Теперь, чтобы отразить @ Предложение Шеллтера , давайте использовать find:

find . -mindepth 1 -maxdepth 1 -type d -exec ./pass-dir-names-with-spaces.sh {} +

Или, если find слишком стар для синтаксиса -exec command {} +:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\0' |
  xargs -0 ./pass-dir-names-with-spaces.sh
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...