我有以下目录结构
root_directory
--sub_a
----index.html
--sub_b
----index.html
--sub_c
----index.css
----index.html
现在我想将文件移动到父目录并在其父文件夹之后重命名,但前提是它们是子目录中的唯一文件。这应该有效地展平目录,如下所示:
root_directory
--sub_a.html
--sub_b.html
--sub_c
----index.css
----index.html
有没有一种聪明的方法来实现这一目标?我可以find . -name 'index.html'
,但我不确定如何另外检查目录是否包含除此之外的文件。我想当我有了这些文件的列表时,我可以将它们向上移动(mv path/index.html ..
),但以某种方式重用文件夹名称来重命名它们可能更聪明。
答案1
假设目录下没有子目录sub_x
,就像sub_x
目录仅包含一个常规文件但包含一个或多个子目录或其他类型的文件或符号链接一样,那么当您被要求用其父目录重命名该文件时,它们将被删除;所以,请注意。
# !/bin/bash
find /path/to/root_directory/ -type d -execdir bash -c '
for file in "$1"/*; do
[[ -f "$file" ]] && (( $((++filesCount)) > 1 )) && exit 1;
done;
((filesCount==1)) && echo mv -v "$file" "${file%/*}.${file##*.}" && echo rm -r "$1"
' _ {} \; 2>/dev/null
空运行输出:
mv -v ./sub_b/index.html ./sub_b.html
rm -r ./sub_b
mv -v ./sub_a/index.html ./sub_a.html
rm -r ./sub_a
删除echo
命令中的 s 以执行mv
和rm
命令的实际操作。结果:
root_directory
├── sub_a.html
├── sub_b.html
└── sub_c
├── index.css
└── index.html
find ... -type d -execdir bash -c '...' _ {} \;
find
仅-d
目录并执行内联脚本bash -c '...'
之内(该操作的使用-execdir
)它找到的每个目录。
for file in "$1"/*; do
[[ -f "$file" ]] && (( $((++filesCount)) > 1 )) && exit 1;
done;
遍历返回的目录路径中的所有文件,$1
检查是否是一个-f
文件,然后增加一个变量,同时验证其值是否超过 1(意味着该目录至少有 2 个文件),如果是,则退出内联脚本和find
命令将读取下一个目录以继续处理;exit
用于缩短处理时间,并且不会继续计算该目录中的文件,因为它不符合我们对该目录(仅包含一个文件的目录)的条件。
((filesCount==1)) && mv -v "$file" "${file%/*}.${file##*.}" && rm -r "$1"
检查 filesCount 是否等于 1,然后重命名文件并删除目录;${file%/*}
和${file##*.}
使用是已知的Shell 参数扩展。