Linux脚本或程序以缩短文件名


8

我找不到Linux版本的namemangler并没有取得很大的成功,我需要重命名1000个文件,以便它们在Windows上可读。

有谁知道可以执行此操作的Linux程序?

如果没有,那么脚本可能会起作用,因为我只需要将文件夹中的所有文件重命名为前16个字符。我怀疑脚本路线可能值得一试,但不确定从哪里开始。


2
您可能可以快速编写一个Python或Perl或Ocaml或Ruby脚本来做到这一点。

您为什么不能只使用允许长文件名的vfat文件系统?
wnoise 2012年

2
出于好奇,Windows将无法识别名称多长时间?名称包含什么?
鲍比(Bobby)

Answers:


10

在Debian,Ubuntu及其衍生产品上,如果man rename在命令提示符处输入,将获得重命名实用程序的手册页,该实用程序允许在重命名中使用任意类似于Perl的正则表达式命令。

例如,这将缩短(通过截断)当前目录中的所有文件,使其长度为五个:

rename 's/^(.{5}).*/$1/' *

它的工作原理是捕获前五个字符,然后在替换中使用该字符,然后删除其余字符。

另一个示例是在保留扩展名的同时将文件名(无扩展名)缩短为五个字符:

rename 's/^(.{5}).*(\..*)$/$1$2/' *

它捕获两个组,第一个是前五个字符,第二个是扩展名。这将myCarefullyCraftedDocument.pdf变成myCar.pdf

警告:谨慎使用最好在目录的副本上使用,或者先进行备份。你被警告了!!最起码,rename -n请先使用,它会告诉您将要执行的操作而不实际执行。


1
这样可以摆脱PDF中的前缀吗?一旦缩短同名文件会发生什么?

是的,那个特定的例子将是。您可以编写一个正则表达式来保留扩展名。我将更新答案。它还可以防止覆盖已经存在的文件,因此以后的重命名将失败。

感谢您对此的帮助-非常感谢。如果将某些pdf重命名为5,我确实有一个小问题,说它尝试使用相同名称重命名的PDF会发生什么?这是我们可以在所有数字上添加唯一数字的一种方法吗?请参阅下面的ename -n's / ^(。{5})。*(\ .. *)$ / $ 1 $ 2 /'*附件123114345234525.pdf重命名为Annex.pdf附件123114432452352.pdf重命名为Annex.pdf

@Grimlockz,我认为您无法将这种智能应用于重命名正则表达式本身。你可能需要做的是写一个脚本包重命名那种智慧,那最好问作为一个单独的问题,所以你会得到更多的人响应不仅仅是一

@Grimlockz这就是为什么您不想在正则表达式中做所有事情的原因。编写使用正则表达式的脚本会更快乐,而且更好。
Spencer Rathbun'2

3

您可以将冲突的文件移动到其他目录:

for i in *
do
    j=${i:0:16}

    if [ -e "$j" ]
    then
        mv "$i" /path/to/rename/later
    else
        mv "$i" "$j"
    fi
done

1

您可以编写脚本来缩短文件名,并删除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)以递归方式扩展到当前目录下的所有文件,首先嵌套更深的文件。


1

用Shell / python / perl脚本编写这种东西就可以了,但是看起来gui应用程序最适合您,因此我建议pyRenamer,它可以精确地完成您想要的事情,以及其他许多事情(简单的常用操作)通过预设[消除空格,将文件名从一个点截断到另一点],简单的搜索/替换,复杂的正则表达式,预览器等)。

您的发行版甚至可能会将其存储在其软件存储库中(Fedora确实如此)。


0

某些系统没有该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模式,您可以调整其运行的文件,并单独使用*其在所有文件上运行。


1
不需要使用echo管道(如果您有很多文件,可能会非常昂贵),请改用heredoc或herestring。
克里斯·

1
@ChrisDown 看到这里根据Wiki的文章,管道进程是分叉的,但是它并没有说明在它们自己的shell中运行它们。
Spencer Rathbun 2012年

1
例如,请注意之间的差值eval 'echo $BASH_SUBSHELL'eval 'echo $BASH_SUBSHELL' | cat
克里斯·

2
我只是做了一个快速测试,time使用echo $i | sed和进行了一个循环sed ... <<<$i,结果字符串大约花费了回声的2/3。
凯文(Kevin)

1
@SpencerRathbun是的。<<启动here <i> doc </ i>,该文件为多行并且需要定界符。<<<创建一个here <i>字符串</ i>,该字符串只需要一个变量/字符串。试试看var=abc // cat<<<$var // cat <<$var
凯文(Kevin)

0

如果您需要尝试重命名文件并且碰巧在系统上安装了KDE库(或者不介意添加它们),请查看krename。

它使您可以直接使用其工具直接执行许多简单的重命名任务,还可以针对更复杂的情况使用正则表达式。

当您建立重命名条件时,它显示了重命名文件的预览。它还允许您再次重命名相同的文件,如果您想做一些复杂的事情,这很有用,因为分阶段执行可以将每个阶段的复杂性降低到您可以快速解决的问题。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.