bash 从文件名中提取第一个数字

bash 从文件名中提取第一个数字

我正在尝试移动这样的文件:

...
DLG023-00-01-sprite.TextGrid.json
DLG023-00-01.prosody.json
DLG023-01-01-sprite.ogg
DLG023-00-02-sprite.TextGrid.json
DLG023-00-02.prosody.json
DLG023-01-02-sprite.ogg
...
DLG028-00-01-sprite.TextGrid.json
DLG028-00-01.prosody.json
DLG028-01-01-sprite.ogg
...

到各自的文件夹中,例如:将文件移动到dialogue023/以 开头的文件夹DLG023;移动到dialogue024/以 开头的文件夹DLG024;等等。

所有文件和目录都处于同一级别。

换句话说,我正在尝试生成如下命令:

mv DLG023-00-01-sprite.ogg dialogue023/

如何从文件名中提取第一个数字?

到目前为止我已经得到了这个:

for i in DLG*-*-*-sprite.ogg; do echo "${i//[^0-9]}";done

但是,当我只想要第一个数字(例如:23)时,它会输出所有数字(例如:230001)。

答案1

我假设你正在使用 OS X,它没有该-t选项mv。如果脚本要处理数千个文件,速度会非常慢。

    for file in DLG*; do
    # Extract the three digits after DLG
    getnum=${file%%-*}
    getnum=${getnum#???}

    # make the directory dialogue### or exit if there is an error
    echo mkdir -p "dialogue${getnum}" || exit

    echo mv "$file" "dialogue${getnum}"
    done

如果输出令人满意,则删除echo之前的。mkdirmv

答案2

您可以使用以下命令生成 mv 命令:

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done

现在,命令打印如下:

mv "DLG023-00-01.prosody.json" "dialogue023/"
[...]
mv "DLG028-00-01.prosody.json" "dialogue028/"
[...]

如果这是您想要的,只需将该输出传输到以下管道bash,它就会被执行:

for f in DLG*; do echo "$f" | sed 's/DLG\([0-9]\+\).*/mv "\0" "dialogue\1\/"/g'; done | bash

答案3

一行解决方案使用find

find . -name DLG* -exec bash -c 'DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/"); mkdir "$DEST"; mv "$0" "$DEST"' {} \;
  • findDLG*命令从该目录中查找文件。
  • 对于每个结果都执行该bash -c句子。

bash句子中:

  • DEST=$(echo "$0" | sed -r "s/DLG([0-9]+)-.*/dialogue\1/");从 find ( $0) 中选择每个结果,并使用将第一个(DLG([0-9]+)-.*)sed之前的所有数字替换为后面的这些数字 ( ),并将其放入名为 的变量中。-dialoguedialogue\1DEST
  • mkdir "$DEST"创建所需的文件夹。
  • mv "$0" "$DEST"'将文件移动到该目录。

答案4

一些想法:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i//[^0-9]}" | head -c 2; echo ;done

如果你确定它们的长度都相同:

for i in DLG*-\*-\*-sprite.ogg; do echo "${i:3:3}" ;done

相关内容