![从所有文件中删除第一个字符(如果其为“0”)](https://linux22.com/image/127209/%E4%BB%8E%E6%89%80%E6%9C%89%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%A0%E9%99%A4%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%EF%BC%88%E5%A6%82%E6%9E%9C%E5%85%B6%E4%B8%BA%E2%80%9C0%E2%80%9D%EF%BC%89.png)
我有几个文件夹:
1
2
3
4
5
所以在每个文件夹中我都有类似的文件
00123.mp3
00133.mp3
00150.mp3
所以我想删除所有0如果它们位于文件名的开头
我试过这个
for file in *; do echo mv "$file" "${file//[ ()@0]/}"; done
但它删除了所有0在开始和内部文件名(我需要在开始时)这在子目录中也不起作用
答案1
如果您使用的是 bash,此脚本将执行您的要求:
#!/bin/bash
shopt -s extglob
while IFS= read -d '' f ; do
file=${f##*/}
dir="${f%/*}/"
echo \
mv "$dir$file" "$dir${file##+(0)}"
done < <(find . -type f -name '0*.mp3' -print0)
一旦您同意要移动的文件列表,请注释该echo \
行以实际执行命令。mv
或者这个 sh 版本的可移植性:
#!/bin/sh
find . -type f -name '0*.mp3' -print |
while IFS= read f; do
file=${f##*/}
dir="${f%/*}/"
f2=$file; until [ "$f2" = "${f2#0}" ]; do f2=${f2#0}; done
echo \
mv "$f" "$dir${f2}"
done
答案2
由于您的问题被标记为 Linux,因此您可以使用rename
或prename
命令(请注意,prename
虽然并未弃用,但仍然有效)。无论哪种情况,它们都是用于基于模式的重命名的 Perl 脚本。
通过组匹配并使用*.mp3
glob 仅传递.mp3
文件,您可以执行以下操作:
$ prename -nv 's/(^0*)(.*).mp3/$2.mp3/' *.mp3
Deprecated program in use: rename as shipped with the Debian perl package will be removed after the release of stretch. Please install the separate 'rename' package which will provide the same command.
000004500.mp3 renamed as 4500.mp3
00123.mp3 renamed as 123.mp3
00133.mp3 renamed as 133.mp3
00150.mp3 renamed as 150.mp3
请注意,-n
和-v
用于试运行和详细输出;仅测试。删除-n
以使实际重命名生效。
如果您对rename
vs感到困惑prename
,您可以阅读相应的答案这消除了混乱,但是......我建议你不要为此烦恼。太复杂了:) 要点是,无论哪种情况,它都会按所示工作,除非您使用的是ksh
shell。
重命名子文件夹中的文件的递归方法是 via find
,但这需要一些带有替换模式的杂技来处理文件路径中的前面的项目,如 所提供的find
。
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(\/0*)(.*).mp3/$1\/$3.mp3/' {} \;
上述命令在测试用例中执行如下:
$ find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/(.*)(\/0*)(.*).mp3/$1\/$3.mp3/' {} \; 2>/dev/null
./testdir/000004500.mp3 renamed as ./testdir/4500.mp3
./testdir/00150.mp3 renamed as ./testdir/150.mp3
./testdir/00133.mp3 renamed as ./testdir/133.mp3
./testdir/00123.mp3 renamed as ./testdir/123.mp3
小的改进可能是指定\d
,数字类别:
find ./testdir/ -type f -name "*.mp3" -exec prename -nv 's/\/0*(\d*\.mp3)/\/$1/' {} \;
Stéphane Chazelas 在评论中提到了可能/0/1.mp3
会被意外重命名为 的可能性.//1.mp3
。我已经采取了几个测试用例;./testdir/0/000987.mp3 renamed as ./testdir/0/987.mp3
并./testdir/007/00123.mp3 renamed as ./testdir/007/123.mp3
得到了结果。我认为贪婪匹配0*
可以解决问题。他还在评论中建议添加[^/]
文件名模式匹配。这是一个好主意,因为 Unix 文件名中不能有反斜杠;路径可以,但不能是单个文件。但是,我不太确定如何更好地实现这一点,并且仍然没有关于文件名匹配0.mp3
或000.mp3
类型的建议。
答案3
和zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '0#(*.mp3)' '$1'
(高兴时删除-n
(空运行))。
#
in 中的全局运算符类似于zsh
正*
则表达式运算符。
请注意,它将重命名0000.mp3
为.mp3
.为了避免这种情况,您可以更改它:
zmv -n '0#([0-9]*.mp3)' '$1'
递归地:
zmv -n '(**/)0#([0-9]*.mp3)' '$1$2'
要按照您的示例建议删除() @
字符,您可能需要执行以下操作:
zmv -n '(**/)0#([0-9]*.mp3)' '$1${2//[() @]}'
(但是,它不会从文件名中删除那些不以数字开头的字符)。