![以 2 为一组选择列表中的元素 - Bash](https://linux22.com/image/921821/%E4%BB%A5%202%20%E4%B8%BA%E4%B8%80%E7%BB%84%E9%80%89%E6%8B%A9%E5%88%97%E8%A1%A8%E4%B8%AD%E7%9A%84%E5%85%83%E7%B4%A0%20-%20Bash.png)
我正在尝试使用序列选择文件列表中的元素。为此,我按照文件夹中的模式创建了一个包含所有文件的列表:
ls -d -1 /my/path/S1*.zip
输出内容为:
/my/path/S1A_IW_SLC__1SDV_20180412T171648_20180412T171715_021437_024E95_BDA1.zip
/my/path/S1A_IW_SLC__1SDV_20180424T171648_20180424T171715_021612_02540A_BB21.zip
/my/path/S1A_IW_SLC__1SDV_20180506T171649_20180506T171716_021787_025996_98AB.zip
/my/path/S1A_IW_SLC__1SDV_20180518T171649_20180518T171716_021962_025F27_A15C.zip
/my/path/S1A_IW_SLC__1SDV_20180530T171650_20180530T171717_022137_0264C8_5D94.zip
/my/path/S1A_IW_SLC__1SDV_20180611T171651_20180611T171718_022312_026A3D_BBFC.zip
/my/path/S1A_IW_SLC__1SDV_20180623T171652_20180623T171719_022487_026F7C_450E.zip
/my/path/S1A_IW_SLC__1SDV_20180623T171652_20180623T171719_543456_64324F_452W.zip
我想创建一个for
循环,每次迭代时,文件以两组为单位进行处理。因此,在第一次迭代中,将处理列表中位置 1 的文件和位置 2 的文件。在第二次迭代中,将处理位置 3 的文件和位置 4 的文件,等等。
为了简单起见,我将以 2 个文件为一组来解压为例:
for i in $(ls -d -1 /shared/Training/WROC0320_UrbanMapping_Germany/Original/S1*.zip)
do
unzip i
unizp i+1 # Not sure if i+1 works like that in `bash`
done
我认为这种方法的问题是,在第一次迭代中它会起作用(i
将是 1 和 2),但在第二次迭代中将i
是 2 和 3,而它应该是 3 和 4。
我的问题是,如何迭代ls
这种方式的结果?
答案1
一般来说,你应该避免迭代结果ls
- 例如参见
与循环相比for
,while
循环可以让你更好地控制分隔符和文件选择。例如:
printf '%s\0' my/path/*.zip | while IFS= read -r -d '' f1 && IFS= read -r -d '' f2; do
echo 'unzipping files'; echo unzip "$f1"; echo unzip "$f2"
done
unzipping files
unzip my/path/S1A_IW_SLC__1SDV_20180412T171648_20180412T171715_021437_024E95_BDA1.zip
unzip my/path/S1A_IW_SLC__1SDV_20180424T171648_20180424T171715_021612_02540A_BB21.zip
unzipping files
unzip my/path/S1A_IW_SLC__1SDV_20180506T171649_20180506T171716_021787_025996_98AB.zip
unzip my/path/S1A_IW_SLC__1SDV_20180518T171649_20180518T171716_021962_025F27_A15C.zip
unzipping files
unzip my/path/S1A_IW_SLC__1SDV_20180530T171650_20180530T171717_022137_0264C8_5D94.zip
unzip my/path/S1A_IW_SLC__1SDV_20180611T171651_20180611T171718_022312_026A3D_BBFC.zip
unzipping files
unzip my/path/S1A_IW_SLC__1SDV_20180623T171652_20180623T171719_022487_026F7C_450E.zip
unzip my/path/S1A_IW_SLC__1SDV_20180623T171652_20180623T171719_543456_64324F_452W.zip
这里printf '%s\0' my/path/S*.zip
将 shell glob 扩展为一个由 NULL 字符(Unix 文件路径中唯一可能不出现的字符)明确分隔的列表,然后每个read
命令读取其中一个。IFS=
取消设置字段分隔符 - 这样做的唯一效果是防止 sread
删除前导空格(在极不可能的情况下,您需要处理此类名称)。
一种可能更干净的方法是,使用set
内置命令和 shell glob 将文件名明确地读入位置参数数组$@
:
shopt -s nullglob
set -- my/path/S*.zip
while (($# > 1)); do
echo "unzipping files";
echo unzip "$1"; echo unzip "$2";
shift 2
done
答案2
以二为步长循环一个版本排序数组。
#!/bin/bash
eval \
"a=($(ls -v1 --quoting-style=shell-escape files/*))"
for ((i=0; i<${#a[@]}; i+=2)); do
[[ -r ${a[$i]} ]] && \
unzip "${a[$i]}"
[[ -r ${a[(i+1)]} ]] && \
unzip "${a[(i+1)]}"
done