在 Linux 中批量重命名文件

Posted

技术标签:

【中文标题】在 Linux 中批量重命名文件【英文标题】:Batch Renaming of Files in Linux 【发布时间】:2013-12-16 14:01:57 【问题描述】:

我有大约 1000 个文件需要重命名。当前格式为:

exten-B12345678910-C45679891254-D12345645-E4578981-G6546525.1.wav

我想删除 exten--G6546525.1 。文件名的“exten-”部分在所有文件中都相同,但 -G6546525.1 部分在所有文件中不同。是否有脚本可以删除这两个部分并仅保留 B12345678910-C45679891254-D12345645-E4578981.wav 作为文件名?

希望我已经说清楚了。

【问题讨论】:

执行此操作的最佳方法取决于您使用的操作系统。 sed 几乎可以肯定是错误的方法。因此,请告诉我们操作系统,如果是 UNIX,请告诉我们您正在使用的 shell。更新您的标签以匹配。 所有文件都在同一个文件夹中,还是在不同的子文件夹中? -G6546525.1 部分有多“不同”?除了数字值之外,它们是否相同? 首先,非常感谢您的及时回复。 我正在使用 Cent OS,目前在 shell 中,但希望稍后运行 cron,所有文件都在同一个目录中。是的 -G6546525.1 是随机的。我希望可以通过表示最后一个“-”来删除它? 你说你在“shell”中。哪个壳? 【参考方案1】:
for f in "exten-*-G*.wav" ; do
    mv "$f" "$(echo $f | sed 's/exten-\(.*\)-[^-]*\.wav/\1.wav/')"
done

这旨在处理指定的文件格式,并且在出现通配符等情况下可能会失败。

【讨论】:

@EdMorton 是的,我同意。 OP 对文件名格式非常具体,所以我确实假设了这个狭窄的定义。 很公平,如果有不明显的警告,那就值得一提。你可以通过适当地引用你的shell变量(即echo "$f"而不是echo $f)和使用printf而不是echo来解决很多问题。 谢谢小伙子,我会全力以赴,让你知道。【参考方案2】:

以下是如何使用 bash 或 ksh 获取您想要的文件名部分:

$ x="exten-B12345678910-C45679891254-D12345645-E4578981-G6546525.1.wav"
$ echo "$x"
exten-B12345678910-C45679891254-D12345645-E4578981-G6546525.1.wav

$ y="$x#*-"
$ echo "$y"
B12345678910-C45679891254-D12345645-E4578981-G6546525.1.wav

$ z="$y%-*"
$ echo "$z"
B12345678910-C45679891254-D12345645-E4578981

澄清如何使用上述重命名文件:

for x in *
do
    y="$x#*-"
    mv -- "$x" "$y%-*.wav"
done

请注意,其他 shell 可能有更简单的方法,例如zsh 有一些强大的结构,一些 shell 有一个 rename 命令。

【讨论】:

frig,我对快速响应感到不知所措,但我还没有说清楚;这是一个实际的文件名:exten-03333456781-07548994578-20131130-135035-1385819435.41.wav。你可能会认为这是来自 freepbx/asterisk 的录音。我在 B、C、D、E、G 中添加了最初是为了向你们识别文件名的每个部分。请原谅我不识字,可耻的是我在微软领域开始了我的职业生涯:(# @user3052324 你可以使用 Ed 的方法来构造你想要的文件名并使用 shell for 来进行重命名。 @user3052324 明白,我更新了我的答案以明确应用程序。【参考方案3】:

我使用在我的 linux 机器上运行的 php 和 phpSecLib2 来完成这种批处理工作。

使用 SecLib,在要重命名文件的 Linux 机器上运行 SSH 连接,然后在文件夹中运行“ls”。然后将文件列表分解成一个 PHP 数组,然后是 for each 循环。

示例代码如下(假设服务器上的文件位置在 /home/user/files/ 并且服务器位置是 localhost):

    <?php

include('Net/SSH2.php');

$ssh = new Net_SSH2('localhost');
if (!$ssh->login('SSHUSER', 'SSHPASS')) 
                exit('Login Failed');


$filelist = $ssh->exec("cd /home/user/files;ls");

$filearray = explode("\n", $filelist);

foreach ($filearray as $key) 

    $newarray = explode("-", $key);
    $newfile = $newarray[1] . $newarray[2] . $newarray[3] . $newarray[4] . ".wav";
    $newfile = (string)$newfile;
    $oldfile = (string)$key;

    $rename = "cd /home/user/files;mv '" . $oldfile . "' '" . $newfile . "'";
    $rename = (string)$rename;
    $runrename = $ssh->exec($rename);

echo "Done!";
?>

上述代码只需少量更改(用户名/密码和文件夹位置更改)即可工作。

【讨论】:

另外,您可以使用 str.split 在 python 中编写几乎相同的脚本 这似乎违背了传统观念,即您永远不应该尝试解析 ls 的输出(谷歌它),如果我正确理解脚本,它不会在 mv 和所以对通配符和其他字符的各种错误持开放态度。 已修复 - 忘记 (string)$key 并在 mv 部分将 $key 更新为 $oldfile。至于解析ls - 解析ls 和解析ls 的输出是有区别的。我多年来一直通过 PHP 做这件事,没有任何问题。 Ed、Mbratch 和 Xarus,你们让我的星期六变得更好了!非常感谢所有人,它现在正在工作。我已经在我的脚本中实现了 Ed 的代码,效果很好。 Ed 请 ping 我你的 paypal;我想捐一点钱。艾登

以上是关于在 Linux 中批量重命名文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux 中批量移动复制追加和重命名文件

如何批量重命名文件夹下的Excel文件

批量重命名文件

DOS按规则批量重命名所有(子)目录下文件

DOS按规则批量重命名所有(子)目录下文件

linux下的文件操作——批量重命名