我有一个文件夹,里面有一堆文件,结构如下:
image_<N1>_<N2>.png
其中 N1 范围为 0:238002,N2 范围为 0:3。
我只想将 N1 <= 18003 和 N2 == 0 的文件移动到另一个文件夹。有没有快速简便的方法可以做到这一点?
N1 的格式不是固定位数。例如,N1=23 将是image_23_0.png
,不是 image_000023_0.png
。
操作系统是 Ubuntu。
答案1
你bash
可以这样做:
mv image_{0..18003}_0.png target_dir/
与N2
往常一样0
,可以将其用作固定字符串。
{a..b}
计算范围从a
到的所有选项b
。这也适用于字母表,但要小心使用除 26 个字母表以外的其他语言环境。
为了避免由于参数列表太长而导致的错误,请使用xargs
seq 0 18003 | xargs -I{} mv image_'{}'_0.png target_dir/
xargs
是一个将输入列表转换为一系列命令的工具,重点是尽可能少地运行命令。简而言之。
这里seq
创建了一个从 0 到 18003 的数字序列,该序列通过管道传输(|
= 转发)作为的输入xargs
。-I{}
表示用传入的输入替换{}
指定的命令以创建一系列命令。
答案2
另一种方法是使用稍长一些的 bash 脚本来执行所有操作,充分利用 bash 的模式匹配和模式提取运算符。如下所示:
# Be sure to set this properly - this will
# fail as written
target=<...some other directory>
# adjust these as needed
N1limit=18003
N2value=0
# read from the output of the ls command,
# one line at a time, respecting spaces, etc.
# Using read's default variable (REPLY)
# saves some quoting and mangling headaches.
while IFS=\ read -r; do
fileName="${REPLY}"
# CONSIDER ADDING LOGIC HERE TO CHECK IF fileName
# a) refers to a file, not a directory, and
# b) matches the desired pattern;
# IF IT DOESN'T, continue to the next file
# get everything up to the end of N1
N1End="${fileName%_*}"
# get N1 itself
N1="${N1End#*_}"
# get everything up to the beginning of N2
N2Start="${fileName##*_}"
# get N2 itself
N2="${N2Start%.*}"
# do the move IFF N1 is at or below the limit
# AND N2 is equal to the desired value
if [[ $n1 -le $N1limit && $N2 -eq $N2value ]]; then
mv "${fileName}" "${target}"
fi
done <<<$(ls)