如何同时重命名和覆盖 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'
我文件夹里有多个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'