![Bash:使用单个 For In 循环迭代 2 个列表](https://linux22.com/image/83435/Bash%EF%BC%9A%E4%BD%BF%E7%94%A8%E5%8D%95%E4%B8%AA%20For%20In%20%E5%BE%AA%E7%8E%AF%E8%BF%AD%E4%BB%A3%202%20%E4%B8%AA%E5%88%97%E8%A1%A8.png)
假设我有 2 个独立的循环
for file1 in `ls Dir1/` ; do
echo $file1
done
for file2 in `ls Dir2/` ; do
echo $file2
done
我想要单循环迭代两个目录伪代码
for file1 , file2 in `ls Dir1` , `ls Dir2`
do
echo $file1
echo file2
done
是否可以
答案1
while
假设文件名中没有换行符,具有适当输入的循环可以完成这项工作。
paste -d/ <(ls /var) <(ls /usr) |
while IFS=/ read -r e u; do
printf '%s\n' "$e $u"
done
答案2
shopt -s nullglob
dir1names=( Dir1/* )
dir2names=( Dir2/* )
while [ "${#dir1names[@]}" -gt 0 ] &&
[ "${#dir2names[@]}" -gt 0 ]
do
printf '%s\n' "${dir1names[0]##*/}"
printf '%s\n' "${dir2names[0]##*/}"
dir1names=( "${dir1names[@]:1}" )
dir2names=( "${dir2names[@]:1}" )
done
这用于bash
将每个目录中的所有路径名获取到两个数组中。然后,它在数组之间交替打印这些路径名的文件名部分(就像ls
所做的那样),并从数组中删除打印的整体。当其中一个数组完全为空时,它会停止。
shellnullglob
选项使不匹配的通配模式展开为空,而不是保持不展开。
测试:
$ tree
.
|-- Dir1
| |-- file-1
| |-- file-2
| |-- file-3
| `-- file-4
|-- Dir2
| |-- otherfile-1
| |-- otherfile-2
| |-- otherfile-3
| |-- otherfile-4
| |-- otherfile-5
| `-- otherfile-6
`-- script.sh
2 directories, 11 files
$ bash script.sh
file-1
otherfile-1
file-2
otherfile-2
file-3
otherfile-3
file-4
otherfile-4
如果这是实际上关于根据文件名称将文件配对,以便一个目录中的文件与另一个目录中的相应文件配对(似乎有时在生物信息学应用程序中完成),那么您最好只迭代其中一个集合进而建造另一组中相应文件的名称。
假设文件被调用something_R1_more
并且something_R2_more
在哪里something
并且more
正在识别特定的文件R1
对R2
。
for r1 in dir1/*_R1_*; do
r2=${r1##*/} # dir1/something_R1_more --> something_R1_more
r2=dir2/${r2/_R1_/_R2_} # something_R1_more --> dir2/something_R2_more
if [ ! -f "$r2" ]; then
printf '%s not found\n' "$r2" >&2
exit 1
fi
# process "$r1" and "$r2" here
done
答案3
你一般不想解析的输出ls
。
在这里,zsh
(您已经在使用zsh
语法,而不是bash
因为您没有引用变量并使用命令替换而不禁用通配符),您可以这样做:
dir1_file_names=(dir1/*(N:t))
dir2_file_names=(dir2/*(N:t))
for f1 f2 (${dir1_file_names:^dir2_file_names})
printf '%s\n' "f1: $f1, f2: $f2"
zsh
可以循环多个变量。${a:^b}
是一个数组压缩操作员。如果其中一个数组的元素少于另一个数组的元素,则就好像它们被截断为最小的长度一样。
如果要比较两个目录中的文件名,另请参阅其数组交集和减法运算符:
file_names_in_both_dir1_and_dir2=(${dir1_file_names:*dir2_file_names})
file_names_only_in_dir1=(${dir1_file_name:|dir2_file_names})
file_names_only_in_dir2=(${dir2_file_name:|dir1_file_names})
答案4
多个变量的输出可以保存在单个变量中,如下所述。检查它是否适合您
#!/bin/bash
cd /
for file1 in $(ls /usr/ ; echo "::::::NEXT:::::::" ; ls /sys/)
do
echo $file1
done