我可以在ubuntu-bash和windows/cygwin-bash上重现这个问题。这个问题发生在文件名和目录名中有空格的情况下。这是我的脚本,名为pass-dir-names-with-spaces.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忽略了我的语录!看来"$@"行为不端!如何过滤掉文件名?
感谢
齐格弗里德
传递目录名的方式不对。
您需要像这样重新构建调用(perl脚本的简化版本(:
readarray -t -d '' dirs < <(perl -e 'print "$_x00"')
./pass-dir-names-with-spaces.sh "${dirs[@]}"
set --
:清空参数数组for d in *; do
:将每个目录条目作为变量d
进行迭代[ -d "$d" ] && set -- "$@" "$d"
:如果条目d
是目录,则将其添加到参数数组中./pass-dir-names-with-spaces.sh "$@"
:最后将参数数组传递给脚本或命令
set --
for d in *; do
[ -d "$d" ] && set -- "$@" "$d"
done
./pass-dir-names-with-spaces.sh "$@"
现在,为了反映@Shellter的建议,让我们使用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 ' |
xargs -0 ./pass-dir-names-with-spaces.sh