Shell 脚本,遍历文件夹

Dav*_*d M 1 bash shell

我的 Mac 上有大量子文件夹,每个子文件夹中都有随机数量的 csv 文件。我想要做的是将这些文件合并到每个目录的单个文件中。

到目前为止,我知道我可以将这些文件与 合并cat * > mergedfile.csv,但是我在遍历所有文件夹时遇到了问题。到目前为止,我以某种方式设法合并了各种各样的东西,但我似乎无法完全按照我的意愿去做。

关于做到这一点的最佳方法的任何想法?

for DIR in ./subfolder/*
do
    cat $dir/* > merged.csv 
done
Run Code Online (Sandbox Code Playgroud)

slh*_*hck 5

使用find,您可以递归列出符合特定条件(例如文件名)的所有文件。

for file in $(find . -type f -name "*.csv"); do cat "$file" >> /path/to/output.csv; done
Run Code Online (Sandbox Code Playgroud)

分解它,find . -name "*.csv"将从您所在的当前文件夹中找到所有 CSV 文件 ( .),并且循环将遍历该列表,将所有内容附加到output.csv文件中。

但是:带有空格、通配符和换行符的文件名在这里可能很棘手。更安全的解决方案是仅exec用于 find 命令。

find . -name "*.txt" -exec cat '{}' >> /path/to/output.csv ';'
Run Code Online (Sandbox Code Playgroud)

在这里,'{}'将被 find 替换为文件名。可以在此处找到有关为什么会出现这种情况以及如何规避问题的长时间问答。

现在,如果您想为每个目录创建一个 CSV 文件——抱歉,之前没有看到——,我可能会这样做:

for dir in $(find . -type d); do find $dir -maxdepth 1 -name "*.csv" -exec cat {} >> "$dir/out" ';'; mv "$dir/out" "$dir/merged.csv"; done
Run Code Online (Sandbox Code Playgroud)

尽管下面 Franck 的解决方案可能更有效。


当然,要注意>和之间的区别>>。前者在写入文件之前总是将文件截断为零长度,而后者只会附加到文件中。

工作的原因cat *.csv > merged.csv——以及为什么在你的循环中,它不会工作——是外壳之前会扩展通配符,所以基本上它会看到:

cat file1.csv file2.csv file3.csv > merged.csv
Run Code Online (Sandbox Code Playgroud)

......这当然不会覆盖任何东西。