我可以在ubuntu bash和windowscygwin bash上重现这个问题,这个问题发生在文件和目录名有空格的情况下,这是我的脚本,叫做pass-dir-name-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实现一个过滤器来删除文件名。
用backtickperl的方法是行不通的! 这是我第一次尝试转义空格。
./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\0' |
xargs -0 ./pass-dir-names-with-spaces.sh