问题描述
在以下 bash
脚本中,我正在从路径捕获文件列表到变量的文件列表,然后将其传递到 xargs
进行进一步的操作。
In the following bash
script, I'm capturing file a file list from a path into a variable and then passing it on into xargs
for further operations.
我发现只需 echo
变量即可适当地用空格换行,每行换行符终止。但是,当我 printf
或 echo
转换为 xargs
时,我发现 xargs
似乎也将每行的输入用空格分开。我将在下面的示例中举例说明,并在注释中包含所看到的结果:
I've found that simply echo
ing the variable gives each line with spaces appropriately with a newline terminator for each line. However when I printf
or echo
this over to xargs
, I'm finding that xargs
appears to be splitting the input of each line by spaces as well. I'll illustrate with the following example with comments including the result I'm seeing:
# Using GNU find:
list="$( find '$SOME_PATH' -type f )"
excluded_list="$( egrep -v -f FILE_WITH_PATTERNS_OF_FOLDERS_TO_EXCLUDE <<< $list )"
# This prints out just fine with lines such as "/some/path/here with spaces" on their own line, eg:
# /some/path/here with spaces
# /another/path/here with spaces
# /and yet another/path/here with spaces
echo "$excluded_list"
# But this prints out a line such as the above example "/some/path/here with spaces" broken up like this instead:
# /some/path/here
# with
# spaces
# /another/path/here
# with
# spaces
# /and
# yet
# another/path/here
# with
# spaces
printf "%s" "$excluded_list" | xargs -n 1 -P 1 sh -c 'echo "$0"'
# And the same result as `printf` above:
echo "$excluded_list" | xargs -n 1 -P 1 sh -c 'echo "$0"'
推荐答案
将多个文件名分配给单个变量
是一种反模式,因为除了空字节以外的任何特殊字符都可能出现在文件名
中,并且您不能再次将变量拆分为原始文件名。
It is an antipattern to assign multiple filenames into a single variablebecause any special character except for a null byte may appear in the filenameand you cannot split the variable into original filenames again.
在您的示例中, echo $ excluded_list
可能看起来像保存
原始文件名,但不幸的是不是。尝试在路径名中再插入两个或
个连续的空格,看看会发生什么情况。
作为急救,您可以包装 $ list
用双引号作为<<< $ list
,但它只是一种临时补救措施。
In your example echo "$excluded_list"
may look like preserving theoriginal filenames but unfortunately it isn't. Try to insert two ormore successive whitespaces in your pathname and see what happens.
As a first aid, you can wrap $list
with double quotes as <<< "$list"
but itis no more than a provisional remedy.
解决方法是:
- 将文件名存储在数组中
- 将空字节用作分隔符并通过管道处理结果
例如,您可以说:
while IFS= read -r -d "" f; do
excluded_list+=("$f")
done < <(find "$SOME_PATH" -type f -print0 | egrep -v -z -Z -f FILE_WITH_PATTERNS_OF_FOLDERS_TO_EXCLUDE -)
for f in "${excluded_list[@]}"; do
echo "$f"
done
或
find "$SOME_PATH" -type f -print0 | egrep -v -z -Z -f FILE_WITH_PATTERNS_OF_FOLDERS_TO_EXCLUDE - | xargs -0 -n 1 -P 1 sh -c 'echo "$0"'
请注意 -z
和 -Z
选项是GNU grep的扩展,可能无法在其他平台上使用。
Note that -z
and -Z
options are GNU grep's extensions and may not work on other platform.
这篇关于为什么xargs会在空格上拆分输入,以及如何解析它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!