我试图根据文件名创建一个数组,但遇到了空格问题。这似乎很常见。但是 - 据我所知 - 引号设置正确,我想这一定是数组的构建方式。
to_dump="$(find . -maxdepth 1 -print0 )"
to_dump_array=($to_dump)
read -p " -> " final
case "$final" in
a) for drop in "${to_dump_array[@]}" ;
do cp "$drop" --recursive --force Destination_Folder && \
echo "dropped \"$drop\" ;
done ;;
b) echo "Won't drop anything" ;;
esac
我想应该有一种更好的方法来从查找查询构建数组。另外,我还有哪里错了?
答案1
-print0
不应在$(...)
替换中使用,因为 bash 变量中的字符串以 null 结尾。
我问了一个问题,其答案与这个问题的要求类似:https://stackoverflow.com/a/30469553/1091693
将该答案调整为您的问题:
to_dump=()
while IFS= read -r -d ''; do
to_dump+=( "$REPLY" )
done < <(find . -maxdepth 1 -print0)
这将创建一个名为 的数组to_dump
,并使用该read
命令从 中读取 NULL 分隔的元素find
。这里使用而不是管道的原因< <(...)
是为了避免隐式子shell,这会阻止数组被修改。
值得注意的是,您的原始find
命令可能需要一个-mindepth 1
, 或者它会选择.
(当前目录),您最终将对其进行递归复制。
我注意到你使用-maxdepth 1
作为 find 的参数,所以也许这会更有用:
shopt -s nullglob
to_dump=( * .[!.]* ..?* )
避免find
,这仅使用 bash 内置函数,不会分叉,并且大部分都非常干净。
第一行shopt -s nullglob
是一个 bash(-only) 命令,用于打开该nullglob
选项。该选项的描述如下man 1 bash
:
如果设置,bash 允许不匹配任何文件的模式(请参阅上面的路径名扩展)扩展为空字符串,而不是它们本身。
简单来说,如果您输入*
但与文件不匹配,它将删除*
.默认行为是*
无论如何都将其放在那里。
第二行向数组添加 3 个 glob:
*
:所有不以以下开头的文件.
.[!.]*
.
:所有以一个和一个非字符开头的文件.
。这是为了避免匹配.
和..
目录。..?*
:所有以..
和 至少一个字符开头的文件。添加的原因与之前的 glob 相同,涵盖了它遗漏的情况。
Bash 将 glob 扩展到数组的定义中,并且正确地扩展它们——不会在空格或类似的情况下进行分割。
关于使用 nullglob 的警告:如果您打开了 nullglob,curl google.com/search?q=test
将会导致curl 抱怨您没有传递它的参数,并且ls /var/fasdfasafs*
会给您当前目录的列表。这是默认情况下未打开的原因之一。
答案2
尝试像这样构建数组:
read -d $'\0' -r -a to_dump <<< $(find . -maxdepth 1 -print0)
答案3
find . -maxdepth 1
...在我看来表明你想要:
a=()
for f in ./..?* ./.[!.]* ./*
do [ -e "$f" ] && a+=$f
done
答案4
我不确定你的脚本正在做你认为它正在做的事情。我不认为这会将 find 的 null 终止输出转换为文件名的 bash 数组:
to_dump_array=($to_dump)
您是否检查过 for 循环的输出以了解您得到了什么?
for drop in "${to_dump_array[@]}"
do
echo -e "$drop\n"
done
存在堆栈溢出,并提供了一些有关从 find -print0 填充数组的建议。
https://stackoverflow.com/questions/1116992/capturing-output-of-find-print0-into-a-bash-array
您还可能更好地使用数组索引来处理数组项,而不是尝试直接在 for 循环中分配给变量,它避免了依赖 shell 的正确分割:
for drop in $(seq 0 $((${#to_dump_array[@]} - 1)))
do
cp "${to_dump_array[$drop]}"
这可能不是很流行,但如果您需要使用 bash 数组和多个转义来管理文件名中的空格(以及其他更不寻常的字符),那么您可能会超出 shell 的设计目的。
您可能会发现 python、perl、ruby 等更快、更可靠、更容易管理和调试代码库。
我有许多“危险信号”,我用它们来告诉我何时可能超出了 shell 脚本编写的明智范围。
- 多级转义或空终止来处理所有文件名情况。
- 多层 shell 函数相互调用。
- 复杂的数据结构。即超越字符串、数字。
- 我发现自己在做“性能优化”。
- 表达式中的“线路噪声”。
是的,您当然可以执行上述所有操作,但是您应该这样做吗?说真的......Python、perl、ruby 等。在Python 中就这么简单,你不需要担心转义或带有空格或二进制字符的文件名。
import os
dirListing = os.listdir("somedirectory")
for eachEntry in dirlisting:
doSomething