在终端中将文件重命名为父目录的名称

在终端中将文件重命名为父目录的名称

我必须处理嵌套在目录内的大量文件(每个目录一个文件),类似于以下内容:

fred/result.txt
john/result.txt
mary/result.txt
...

我目前正在使用以下命令来处理每个文件:

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c \"cd '{}' && processResult result.txt\" \;

我正在寻找可以添加到此命令末尾的内容,将文件名更改为fred.txt等,然后将文件移动到父目录中以消除额外的目录层。

实现这个的最佳方法是什么?

答案1

下面的小 Python 脚本将完全按照您描述的方式执行;它将:

  • results.txt根据上级目录重命名给定目录中名为
  • 将其向上移动一级(目录)
  • 删除文件最初所在的目录(现在为空)

结果:

这:

directory
|
├── fred
│   └── results.txt
├── john
│   └── results.txt
└── mary
    └── results.txt

会变成:

directory
|
├── fred.txt
├── john.txt
└── mary.txt

剧本

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for root, dirs, files in os.walk(dr):
    for file in files:
        if file == "results.txt":
            spl = root.split("/"); newname = spl[-1]; sup = ("/").join(spl[:-1])
            shutil.move(root+"/"+file, sup+"/"+newname+".txt"); shutil.rmtree(root)

使用

  • 将以下代码复制到一个空文件中,保存为move_rename.py
  • 通过命令运行:

    python3 /path/to/move_rename.py <directory_to_reorganize>
    

笔记

与往常一样,首先在小样本上进行测试

答案2

我认为这是合法的(使用基于 perl 的rename命令)

find dir -name 'results.txt' -exec rename -nv -- 's|/(.*)/(.*)$|/$1/$1.txt|' {} +

例如

$ tree dir
dir
├── fred
│   └── results.txt
├── john
│   └── results.txt
└── mary
    └── results.txt

3 directories, 3 files

然后

$ find dir -name 'results.txt' -exec rename -v -- 's|/(.*)/(.*)$|/$1/$1.txt|' {} +
dir/fred/results.txt renamed as dir/fred/fred.txt
dir/john/results.txt renamed as dir/john/john.txt
dir/mary/results.txt renamed as dir/mary/mary.txt

导致

$ tree dir
dir
├── fred
│   └── fred.txt
├── john
│   └── john.txt
└── mary
    └── mary.txt

3 directories, 3 files

如果你只需要去下面 1 级dir,你可以简单地做

rename -vn -- 's|/(.*)/(.*)$|/$1/$1.txt|' dir/*/results.txt

与往常一样,该-n选项保留用于测试目的

答案3

我们可以使用经典方法:find 组合while read

演示:

$ ls *
fred:
results.txt

jane:
results.txt

john:
results.txt

$> find . -type f -name "results.txt" -printf "/%P\n" | while read FILE ; do DIR=$(dirname "$FILE" );\                            
>  mv ."$FILE" ."$DIR""$DIR".txt;done                                                                                             
$> ls
fred/  jane/  john/
$> ls *
fred:
fred.txt

jane:
jane.txt

john:
john.txt

使用echo前先用mv你的文件测试一下线路。

轻微改善

我们可以将对 的调用嵌入bash到 exec 中,并进行参数扩展(特别是前缀删除)。基本上就是将脚本嵌入到 exec 调用中。

$> find "$PWD" -type f -name "results.txt" -exec bash -c ' DIR=$( dirname "{}"  ); echo "{}" "$DIR"/"${DIR##*/}".txt  ' \;                
/home/xieerqi/TESTDIR/fred/results.txt /home/xieerqi/TESTDIR/fred/fred.txt
/home/xieerqi/TESTDIR/jane/results.txt /home/xieerqi/TESTDIR/jane/jane.txt
/home/xieerqi/TESTDIR/john/results.txt /home/xieerqi/TESTDIR/john/john.txt

要使命令通用(适用于任何文件,而不仅仅是results.txt),只需删除-name "results.txt"部分。另请参阅这个帖子寻找替代的 Python 解决方案。

答案4

通过 find 执行此操作似乎过于复杂。为什么不使用简单的 for 循环?

for folder in *; do
    (cd "$folder" && processResult result.txt)  # This replaces your previous find(1)
    mv "$folder/result.txt" "${folder}.txt"
    rmdir "$folder"
done

相关内容