【发布时间】:2020-01-05 08:33:22
【问题描述】:
我想创建一个文件名列表 - 其中可能包含一些带有空格的文件名。
此列表应在 bash 中过滤(而不是使用 'find' 本身 - 或类似的)。
必须以某种方式处理最终列表。
我无法让它工作 - 除非使用 associative 数组。
这是我的解决方案。
测试目录:
> find $HOME/test-dir/
/home/frank/test-dir/
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileC
/home/frank/test-dir/FileB
脚本 #1(有效):
> cat test2.sh
#!/bin/bash
mapfile -t Data < <(find $HOME/test-dir/ -type f)
for Key in ${!Data[@]}
do
echo "$Key -> ${Data[$Key]}"
done
echo
# remove #1 element via variable
Del=2
unset 'Data[$Del]'
while read Value
do
echo "$Value"
done < <(IFS=$'\n'; for Value in ${Data[@]}; do echo $Value; done)
echo
注意:脚本末尾的进程替换应该能够处理仅在循环内的值,而无需知道它存储在关联数组中(旧代码)。
输出:
> ./test2.sh
0 -> /home/frank/test-dir/FileA
1 -> /home/frank/test-dir/File D
2 -> /home/frank/test-dir/FileC
3 -> /home/frank/test-dir/FileB
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileB
对于“文件 D”,任何使用纯数组的尝试都会失败。 我可以填充数组,但遍历或尝试删除元素会再次破坏它:
脚本 #2(不起作用):
> cat test2.sh
#!/bin/bash
OLDIFS="$IFS"
IFS=$'\n'
readarray -t Data < <(find $HOME/test-dir/ -type f)
IFS="$OLDIFS" # works only if i drop this
for Value in ${Data[@]}
do
echo "$Value"
done
echo
# remove #1 element via variable
Del=2
unset 'Data[$Del]'
for Value in ${Data[@]}
do
echo "$Value"
done
输出:
> ./test2.sh
/home/frank/test-dir/FileA
/home/frank/test-dir/File
D
/home/frank/test-dir/FileC
/home/frank/test-dir/FileB
/home/frank/test-dir/FileA
/home/frank/test-dir/File
D
/home/frank/test-dir/FileB
有趣的是,删除 IFS 的恢复(参见上面的注释行)会导致
输出:
> ./test2.sh
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileC
/home/frank/test-dir/FileB
/home/frank/test-dir/FileA
/home/frank/test-dir/File D
/home/frank/test-dir/FileB
但我想本地化 IFS 的设置以不干扰旧代码,这依赖于不同的 IFS 值。
有什么方法可以让它与纯数组(不是关联数组)一起工作?
附录:
这也有效:
> cat test2b.sh
#!/bin/bash
readarray -t Data < <(find $HOME/test-dir/ -type f)
while read Value
do
echo "$Value"
done < <(IFS=$'\n'; for Value in ${Data[@]}; do echo $Value; done)
echo
# remove #1 element via variable
Del=2
unset 'Data[$Del]'
while read Value
do
echo "$Value"
done < <(IFS=$'\n'; for Value in ${Data[@]}; do echo $Value; done)
echo
但是不得不这样走有点奇怪。我使用关联数组来替代我的解决方案。但那是因为我自己介绍了 key->value 并且必须只返回值。对于纯数组要求这样做感觉很奇怪。
【问题讨论】:
-
数组和关联数组基于相同的实现。您可以像这里这样以关联数组方式访问您的数组:stackoverflow.com/questions/9084257/…。或者您可以使用流程替代。有更好的方法吗?
-
看看this bash pitfall。它会为您指明正确的方向。