我必须处理嵌套在目录内的大量文件(每个目录一个文件),类似于以下内容:
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