我有一个这样的目录结构:
./BBC_english/
2017-09-19.20.00.3-0.rec/00001.mpeg
2017-09-19.21.00.3-0.rec/00001.mpeg
2017-09-19.22.00.3-0.rec/00001.mpeg
2017-09-19.23.00.3-0.rec/00001.mpeg
我需要将00001.mpeg
./ 中的每个文件夹重命名为父文件夹,例如,我需要以这种格式记录的日期和时间 - 我不需要2017
新的文件名
最后我需要将所有重命名的 mpeg 文件移动到新路径,如下所示:
./newpath/
BBC_english__09-19__20.00.mpeg
BBC_english__09-19__21.00.mpeg
BBC_english__09-19__22.00.mpeg
BBC_english__09-19__23.00.mpeg
首先,我使用 Fedora 20(我知道这里是 Ubuntu 论坛),当我执行mv
命令时,它不支持-v
选项,只有这个选项:
-f -i -n
您应该知道,在源路径中,我的视频录像机每小时创建新文件一次。
因此,我需要一个递归脚本来对源文件夹中的所有文件执行此操作(仅针对 .mpeg 文件)(之后我将在 cron 中使用该脚本)但到目前为止,您在此处发送的脚本均不适合我。
答案1
既然您提到您使用的是 Fedora,这里有一个 Python 脚本,它使用 Python 2 语法,在 Ubuntu 或 Fedora 上都可以正常工作,不会出现任何问题或差异。(如果使用prename
默认提供的 Debian 衍生产品就好了,但不幸的是 Fedora 没有。我将把它留作将来的练习,prename
对 Ubuntu 用户仍然有用。)
脚本本身如下:
#!/usr/bin/env python
import os
import sys
import shutil
def find_files(start_dir):
ext_paths = []
for root,dirs,files in os.walk(start_dir):
if root == start_dir: continue
ext_paths = ext_paths + map( lambda x: os.path.join(root,x),files )
return ext_paths
def alter_path(path,new_dir):
newpath = path.replace(".3-0.rec/00001","").replace("2017-","")
newpath = newpath.replace("BBC_english/","BBC_english__").replace("19.","19__")
return os.path.join(new_dir,newpath)
def main():
for i in find_files(sys.argv[1]):
print(i,alter_path(i,sys.argv[2]))
shutil.copy(i,alter_path(i,sys.argv[2]))
if __name__ == '__main__':
main()
实际操作如下:
$ ./rename_mpegs.py BBC_english/ newpath/
('BBC_english/2017-09-19.23.00.3-0.rec/00001.mpeg', 'newpath/BBC_english__09-19__23.00.mpeg')
('BBC_english/2017-09-19.20.00.3-0.rec/00001.mpeg', 'newpath/BBC_english__09-19__20.00.mpeg')
('BBC_english/2017-09-19.22.00.3-0.rec/00001.mpeg', 'newpath/BBC_english__09-19__22.00.mpeg')
('BBC_english/2017-09-19.21.00.3-0.rec/00001.mpeg', 'newpath/BBC_english__09-19__21.00.mpeg')
$ tree newpath/
newpath/
├── BBC_english__09-19__20.00.mpeg
├── BBC_english__09-19__21.00.mpeg
├── BBC_english__09-19__22.00.mpeg
└── BBC_english__09-19__23.00.mpeg
我建议您shutil.copy()
用 替换部分shutil.move()
,或者您最终可以摆脱旧目录,但我会让您自己决定。
规则很简单:从上一级目录中调用脚本,将源作为参数 1,将目标作为参数 2。BBC_english
总的来说,这个脚本既快又脏,重命名是硬编码的;有人会说它并不理想,但它确实有效。
答案2
希梅尔建议为了回答链接的帖子,您可以使用一系列 shell 扩展。
假设当前工作目录是源和目标的父目录,您可以在 Ubuntu 系统上使用此循环:
$ for d in ./BBC_english/*; do e="${d##*2017-}"; f="${e%%.[0-9]-[0-9].rec}"; g="${f/./__}"; echo mv -v -- "$d"/* ./newpath/BBC_english__"$g".mpeg; done
mv -v -- ./BBC_english/2017-09-19.20.00.3-0.rec/00001.mpeg ./newpath/BBC_english__09-19__20.00.mpeg
mv -v -- ./BBC_english/2017-09-19.21.00.3-0.rec/00001.mpeg ./newpath/BBC_english__09-19__21.00.mpeg
mv -v -- ./BBC_english/2017-09-19.22.00.3-0.rec/00001.mpeg ./newpath/BBC_english__09-19__22.00.mpeg
mv -v -- ./BBC_english/2017-09-19.23.00.3-0.rec/00001.mpeg ./newpath/BBC_english__09-19__23.00.mpeg
请注意,我们循环遍历的是目录而不是文件。这假设每个目录中实际上只有一个文件,从逻辑上看似乎确实如此。
测试后删除echo
以实际移动文件。然后-v
报告mv
其正在做什么。
如果你mv
不支持-v
(verbose) 标志,但又想看看发生了什么,你可以让 bash 变得详细,并为你提供正在执行的操作的详细摘要,方法是使用set -x
#!/bin/bash
set -x
for d in ./BBC_english/*; do
e="${d##*2017-}" # remove everything before and including 2017-
f="${e%%.[0-9]-[0-9].rec}" # remove the trailing numbers and `.rec`
g="${f/./__}" # replace the first `.` with `__`
echo mv -- "$d"/* ./newpath/BBC_english__"$g".mpeg
# move to the new path using the edited directory name
done
删除后,此输出echo
将包括每次扩展的结果和mv
循环每次迭代的语句。对于第一次迭代,输出将如下所示:
+ for d in ./BBC_english/*
+ e=09-19.20.00.3-0.rec
+ f=09-19.20.00
+ g=09-19__20.00
+ mv -- ./BBC_english/2017-09-19.20.00.3-0.rec/00001.mpeg ./newpath/BBC_english__09-19__20.00.mpeg
答案3
该脚本应该有帮助:
#!/bin/bash
for i in ./BBC_english/*; do
# Get the path to the file
path=$(dirname "$(readlink -f "$i")")
# get the names for file rename
f2=$( echo "$path" | grep -Eo "\-[0-9]{2}-[0-9]{2}" | grep -Eo "[0-9]{2}-[0-9]{2}")
f1=$( echo "$path" | grep -Eo BBC_english )
f3=$(echo "$path" | grep -Eo "\.[0-9]{2}\.[0-9]{2}" | grep -Eo "[0-9]{2}\.[0-9]{2}")
# Rename the files
mv -n "$i" ./newpath/"$f1"__"$f2"__"$f3".mpeg
done