在 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 的方法来构造你想要的文件名并使用 shellfor
来进行重命名。
@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 中批量重命名文件的主要内容,如果未能解决你的问题,请参考以下文章