我在目录结构中有一堆文件:
Dir
SubDir
File
File
Subdir
SubDir
File
File
File
很抱歉格式杂乱,但正如您所看到的,所有目录级别都有文件。所有这些文件名都有一个7个数字的字符串,如下所示:1234567_filename.ext。我试图删除文件名开头的数字和下划线。
现在我正在使用bash并使用此oneliner使用mv和cut重命名文件:
for i in *; do mv "$i" "$(echo $i | cut -d_ -f2-10)"; done
这是在CD进入目录时运行的。我很想找到一种递归方式来做这个,所以它只重命名文件,而不是文件夹。我还在shell中使用了一个foreach循环,在bash之外的目录中有一堆包含文件的文件夹而没有其他子目录:
foreach$ set p=`echo $f | cut -d/ -f1`
foreach$ set n=`echo $f | cut -d/ -f2 | cut -d_ -f2-10`
foreach$ mv $f $p/$n
foreach$ end
但只有当文件夹中没有其他子目录时才能使用。
是否有循环或oneliner我可以用来重命名目录中的所有文件?我甚至尝试使用find
,但无法弄清楚如何将cut
合并到代码中。
非常感谢任何帮助。
答案 0 :(得分:2)
使用Perl的重命名(独立命令):
shopt -s globstar
rename -n 's|/[0-9]{7}_([^/]+$)|/$1|' **/*
如果一切正常,请删除-n
。
globstar
:如果设置,路径名扩展上下文中使用的模式**将会 匹配所有文件和零个或多个目录和子目录。如果 该模式后跟一个/,只有目录和子目录 匹配。
答案 1 :(得分:0)
['.../python/lib/python2.7/site-packages/ipykernel/__main__.py', '-f', '.../.local/share/jupyter/runtime/kernel-fd79e9d9-d66f-4cf6-856b-a4a3c3ea73a0.json']
确实提供了函数,这些函数可以递归,但是您不需要为此作业提供递归函数。您只需要枚举树中的所有文件。 bash
命令可以执行此操作,但启用find
的{{1}}选项并使用shell glob来执行此操作更安全:
bash
请注意,这不会验证文件名是否与执行重命名之前指定的模式实际匹配;我带你去听你的话。如果需要这样的检查,那么肯定可以添加。
答案 2 :(得分:0)
对你已经拥有的这个小调整怎么样:
for i in `find . -type f`; do mv "$i" "$(echo $i | cut -d_ -f2-10)"; done
基本上只是用`find来交换*。 -type f`
答案 3 :(得分:0)
应该可以使用find
...
find -E . -type f \
-regex '.*/[0-9]{7}_.*\.txt' \
-exec sh -c 'f="${0#*/}"; mv -v "$0" "${0%/*}/${f#*_}"' {} \;
您的find
选项可能有所不同 - 我在FreeBSD中这样做。这里的想法是:
-E
指示find
使用扩展正则表达式。-type f
仅导致找到普通文件(不是目录或符号链接)。-regex ...
匹配您正在寻找的文件。如果需要,您可以使其更具体。exec ... \;
使用{}
(我们已找到的文件)作为参数运行命令。我们正在运行的命令首先使用参数扩展来获取目标目录,然后使用第二个来剥离文件名。请注意临时变量$f
,它用于解决额外下划线是文件名的一部分的可能性。
请注意,这不是bash
命令,但您当然可以从bash shell运行它。如果您想要一个不需要使用find
等外部工具的bash解决方案,您可以执行以下操作:
$ shopt -s extglob # use extended glob format
$ shopt -s globstar # recurse using "**"
$ for f in **/+([0-9])_*.txt; do f="./$f"; echo mv "$f" "${f%/*}/${f##*_}"; done
这使用与find
解决方案相同的逻辑,但使用bash v4 extglob
提供更好的文件名匹配,并globstar
通过子目录进行递归。
希望这些帮助。