我在一个目录中有一个文件列表,例如..
LDI_P1800-id1.0200.bin
LDI_P1800-id2.0200.bin
...
LDI_P1800-id17.0200.bin
LDI_P1800-id18.0200.bin
...
...
LDI_P1800-id165.0200.bin
LDI_P1800-id166.0200.bin
...
我希望将每个人移动到目录
LDI_P1800-id165.0200.bin to ../id165/.
LDI_P1800-id166.0200.bin to ../id166/.
LDI_P1800-id167.0200.bin to ../id167/.
...
等等。
我的猜测是我必须使用正则表达式从字符串中提取id
for file in *.0200.bin ; do
"extracting id from each file"
mv $file ../id$id/.
done
任何人都可以给我帮助吗?谢谢!!
答案 0 :(得分:6)
尝试以下pure-bash解决方案:
for file in *.0200.bin
do
id=${file#*-} # delete everything upto the first hyphen
id=${id%%.*} # delete everything after the first dot
[[ ! -d ../$id ]] && mkdir ../$id # if the directory doesn't exist create it
mv $file ../$id
done
也可以在sed
中完成,但我更喜欢第一种方法:
for file in *.0200.bin
do
id=$(sed 's/[^-]*-\([^\.]*\).*$/\1/g' <<< $file)
mkdir -p ../$id && mv $file ../$id
done
答案 1 :(得分:1)
您也可以在bash
中使用正则表达式(不仅仅是模式匹配)。
for f in *.0200.bin; do
[[ $f =~ id[0-9]+ ]] && mv -- "$f" ../${BASH_REMATCH[0]}
done
BASH_REMATCH
是一个数组,用于保存最近=~
次匹配的结果。第0个元素包含与整个正则表达式匹配的字符串。非零索引保持正则表达式中第* n *个括号组匹配的结果(如果有)。
答案 2 :(得分:0)
有几种方法可以检索该ID,其中一种方法是使用以下方法:
ID=$(echo $file | grep -o "id[[:digit:]]*\." | cut -b3- | tr -d '.')
它使用grep隔离id[DIGITS].
表达式,然后剪切id
部分,最后使用.
删除tr
字符
事实上,您可以隔离整个id[DIGITS]
部分并在循环中使用它,如下所示:
for file in *.0200.bin ; do
echo "extracting id from each file"
ID=$(echo $file | grep -o "id[[:digit:]]*\." | tr -d '.')
mv $file ../$ID/.
done
更新:正如@dogbane建议的那样,它可以进一步简化为:
for file in *.0200.bin ; do
echo "extracting id from each file"
ID=$(grep -o "id[[:digit:]]*" <<< $file)
mv $file ../$ID/.
done
答案 3 :(得分:0)
另一个纯bash (假设目标目录已经存在):
for file in * ;do [[ $file =~ ^LDI.*id([0-9]+)\..*.bin ]] &&
mv $file ../id${BASH_REMATCH[1]} ; done
如果目录可能不存在,则需要mkdir
。 (警告:当mkdir
是外部命令时,这不再是纯粹的狂欢)
for file in LDI*.bin ;do
if [[ $file =~ ^LDI.*id([0-9]+)\. ]];then
[ -d ../id${BASH_REMATCH[1]} ] ||
mkdir ../id${BASH_REMATCH[1]}
mv $file ../id${BASH_REMATCH[1]}
fi
done
使用mkdir -p
暗示为每个文件执行了一个fork to mkdir ,即使目录已经存在,在这种情况下这也不是一个很好的解决方案。