如何同时重命名和覆盖 Bash 中的部分文件名?

How do I rename and overwrite part of file name in Bash at the same time?

我文件夹里有多个JS文件,例如foo.js, this_is_foo.js, foo_is_function.js.

我想在扩展名“.js”前面附加一个作为参数传递的数字,例如foo.1.js, this_is_foo.1.js, foo_is_function.1.js

我写了一个脚本来第一次成功追加一个数字,但是如果我 运行 脚本两次,它不会覆盖第一个数字,而是在之后追加。

实际结果:foo.js --> foo.1.js (第一个运行 ) --> foo.1.2.js (第二 运行).

预期结果:foo.js --> foo.1.js(第一个运行 ) --> foo.2.js (第二 运行).

这是我的脚本:

#!/bin/sh
param=
for file in *.js; do
    ext="${file##*.}";
    filename="${file%.*}";
    mv "$file" "${filename}.${param}.${ext}";
done

我该怎么做?我想写纯bash脚本,不使用任何工具。

在进行重命名之前,您可以检查文件名 (${filename%.*}) 中最后一个点之后的内容是否为数字。如果是这样,请将其切换为 param 而不是附加新的 param

因为你写的是你想使用纯 bash 我认为可以将 shebang 更改为 #!/bin/bash:

#!/bin/bash
param=
for file in *.js; do
    ext="${file##*.}";
    filename="${file%.*}";

    # Check if what is after the last dot in filename is numeric
    # Then assume that it should be switched to param
    if [[ ${filename##*.} =~ ^[0-9]+$ ]]; then
        mv "$file" "${filename%.*}.${param}.${ext}"

    ## Else add param
    else
        mv "$file" "${filename}.${param}.${ext}"
    fi  
done

试运行

$> touch a.js && find -type f -name *.js && \
 ./test.sh 1 && find -type f -name *.js && \
 ./test.sh 2 && find -type f -name *.js

./a.js
./a.1.js
./a.2.js

您可以使用扩展的 globbing 来匹配可选的 .(数字之前的那个)和 .js 后缀之前的任意数量的数字。

如果变量非空,我还将 . 添加到 $param 变量。这样您就可以调用不带参数的脚本,并删除 .<number> 而不是 added/changed.

#!/bin/bash

shopt -s extglob # enable extended globbing

param=
if [ -n "$param" ]; then
    param=.${param} # add prefix `.`
fi

for file in *.js; do
    newfile=${file%%?(.)*([0-9]).js}${param}.js
    if [ "$file" = "$newfile" ]; then
        echo "skipping \"${file}\", no need to rename"
    elif [ -f "$newfile" ]; then
        echo "skipping \"$file\", file \"$newfile\" already exists"
    else
        mv "$file" "$newfile"
    fi
done

用法:

./script.sh 1 # change suffix to `.1.js`
./script.sh 2 # change suffix to `.2.js`
./script.sh   # change suffix to `.js`

Posix 兼容的解决方案,允许您继续使用 /bin/sh

#!/bin/sh
param=
for file in *.js; do
    ext="${file##*.}";
    filename="${file%.*}";
    [ -z "${filename##*.##*[!0-9]*}" ] && mv "$file" "${filename}.${param}.${ext}" || mv "$file" "${filename%.*}.${param}.${ext}"
done

试运行

$> touch a.js && find -type f -name *.js && \
 ./test.sh 1 && find -type f -name *.js && \
 ./test.sh 2 && find -type f -name *.js

./a.js
./a.1.js
./a.2.js

这可能会满足您的要求。

#!/usr/bin/env bash

counter=1

for file in *.js; do
  if [[ $file =~ (^[^\.]+)(\.js)$ ]]; then
    mv -v "$file" "${BASH_REMATCH[1]}.$counter${BASH_REMATCH[2]}"
  elif [[ $file =~ (^[^\.]+)\.([[:digit:]]+)(\.js)$ ]]; then
    first=${BASH_REMATCH[1]}
    counter=${BASH_REMATCH[2]}
    extension=${BASH_REMATCH[3]}
    ((counter++))
    mv -v "$file" "$first.$counter$extension"
  fi
done

在行动中。

mkdir -p /tmp/123 && cd /tmp/123
touch foo.js
touch this_is_foo.js
touch this_is_foucntion.js

第一个运行

./myscript

输出

renamed 'foo.js' -> 'foo.1.js'
renamed 'this_is_foo.js' -> 'this_is_foo.1.js'
renamed 'this_is_foucntion.js' -> 'this_is_foucntion.1.js'

第二个运行.

renamed 'foo.1.js' -> 'foo.2.js'
renamed 'this_is_foo.1.js' -> 'this_is_foo.2.js'
renamed 'this_is_foucntion.1.js' -> 'this_is_foucntion.2.js'

第三个运行.

renamed 'foo.2.js' -> 'foo.3.js'
renamed 'this_is_foo.2.js' -> 'this_is_foo.3.js'
renamed 'this_is_foucntion.2.js' -> 'this_is_foucntion.3.js'

使用 for loop

for i in {1..5}; do ./script.sh ; done

输出

renamed 'foo.js' -> 'foo.1.js'
renamed 'this_is_foo.js' -> 'this_is_foo.1.js'
renamed 'this_is_foucntion.js' -> 'this_is_foucntion.1.js'
renamed 'foo.1.js' -> 'foo.2.js'
renamed 'this_is_foo.1.js' -> 'this_is_foo.2.js'
renamed 'this_is_foucntion.1.js' -> 'this_is_foucntion.2.js'
renamed 'foo.2.js' -> 'foo.3.js'
renamed 'this_is_foo.2.js' -> 'this_is_foo.3.js'
renamed 'this_is_foucntion.2.js' -> 'this_is_foucntion.3.js'
renamed 'foo.3.js' -> 'foo.4.js'
renamed 'this_is_foo.3.js' -> 'this_is_foo.4.js'
renamed 'this_is_foucntion.3.js' -> 'this_is_foucntion.4.js'
renamed 'foo.4.js' -> 'foo.5.js'
renamed 'this_is_foo.4.js' -> 'this_is_foo.5.js'
renamed 'this_is_foucntion.4.js' -> 'this_is_foucntion.5.js'