我找不到Linux版本的namemangler并没有取得很大的成功,我需要重命名1000个文件,以便它们在Windows上可读。
有谁知道可以执行此操作的Linux程序?
如果没有,那么脚本可能会起作用,因为我只需要将文件夹中的所有文件重命名为前16个字符。我怀疑脚本路线可能值得一试,但不确定从哪里开始。
我找不到Linux版本的namemangler并没有取得很大的成功,我需要重命名1000个文件,以便它们在Windows上可读。
有谁知道可以执行此操作的Linux程序?
如果没有,那么脚本可能会起作用,因为我只需要将文件夹中的所有文件重命名为前16个字符。我怀疑脚本路线可能值得一试,但不确定从哪里开始。
Answers:
在Debian,Ubuntu及其衍生产品上,如果man rename
在命令提示符处输入,将获得重命名实用程序的手册页,该实用程序允许在重命名中使用任意类似于Perl的正则表达式命令。
例如,这将缩短(通过截断)当前目录中的所有文件,使其长度为五个:
rename 's/^(.{5}).*/$1/' *
它的工作原理是捕获前五个字符,然后在替换中使用该字符,然后删除其余字符。
另一个示例是在保留扩展名的同时将文件名(无扩展名)缩短为五个字符:
rename 's/^(.{5}).*(\..*)$/$1$2/' *
它捕获两个组,第一个是前五个字符,第二个是扩展名。这将myCarefullyCraftedDocument.pdf
变成myCar.pdf
。
警告:请谨慎使用,最好在目录的副本上使用,或者先进行备份。你被警告了!!最起码,rename -n
请先使用,它会告诉您将要执行的操作而不实际执行。
您可以编写脚本来缩短文件名,并删除Windows中不受欢迎的bash行中的字符。警告,未经测试的代码,直接输入我的浏览器。
shopt -s dotglob extglob
for x in *; do
y=${x//+([!-!#$%&'().0-9@A-Z^_`a-z{}~])/_} # change all problematic characters to _
if [[ $y = .* ]]; then y=_${y#.}; fi # change dot files to begin with _
y=${y:0:16} # truncate names
y=${y,,} # convert to lowercase
if [[ -e $y || $y =~ ^(aux|clock\$|com[0-9]|con|lpt[0-9]|nul|prn)(\.*)?$ ]]; then
# The file exists or is a DOS/Windows reserved name.
# Change foo.bar to foo~1.bar, foo~2.bar, ... (I ignore the length restriction here)
i=1
if [[ $y =~ \. ]]; then
prefix=${y%%.*}; suffix=.${y#*.}
else
prefix=$y; suffix=
fi
y=${prefix}~$i$suffix
while [[ -e $y ]]; do
((++i))
y=${prefix}~$i$suffix
done
fi
mv -- "$x" "$y"
done
如果需要递归到子目录,请从中调用Shell脚本find -depth -exec …
。或者使用zsh代替bash;在zsh中,**/*(od)
以递归方式扩展到当前目录下的所有文件,首先嵌套更深的文件。
某些系统没有该rename
命令,因此作为paxdiablo答案的替代方法,以下是如何使用做同样的事情mv
。
for f in *.pdf; do
tmp=`echo $f | sed -r 's//^(.{5}).*(\..*)$/$1$2/'`
mv -b ./"$f" ./"$tmp"
done
-b
移动中的标志创建将被删除或覆盖的文件的备份。通过更改for循环中的glob模式,您可以调整其运行的文件,并单独使用*
其在所有文件上运行。
echo
管道(如果您有很多文件,可能会非常昂贵),请改用heredoc或herestring。
eval 'echo $BASH_SUBSHELL'
和eval 'echo $BASH_SUBSHELL' | cat
。
time
使用echo $i | sed
和进行了一个循环sed ... <<<$i
,结果字符串大约花费了回声的2/3。
<<
启动here <i> doc </ i>,该文件为多行并且需要定界符。<<<
创建一个here <i>字符串</ i>,该字符串只需要一个变量/字符串。试试看var=abc // cat<<<$var // cat <<$var
。
for file in *; do
mv "$file" $(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')
done &