Bash:提取文件名的数量,以移动到编号的正确目录

时间:2012-12-21 13:45:56

标签: regex string bash extract

我在一个目录中有一个文件列表,例如..

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

任何人都可以给我帮助吗?谢谢!!

4 个答案:

答案 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 ,即使目录已经存在,在这种情况下这也不是一个很好的解决方案。