我知道我们可以通过cat file [file] [[file] ...] > joined-file
.我有一个目录,其中包含数十万个文件。我想将几组(1000)个文件连接到一个文件中。我有一个非常小的文件集。我想连接 1000 个文件,无论其名称和顺序如何,以便其他服务可以轻松读取并保存内存中的所有文件名以进行操作。
这是我尝试过的
for i in /var/abc/*.csv; do "$i" > file1.csv; rm -rf "$i"; done
但要跟踪另一个变量的计数。有什么有效的方法呢?这样我就不能直接连接1000个文件并移动它们。
为什么是1000?因为该目录包含数十万个文件。我们将每个文件的大小设置为 1-4 KB,只是为了确保一个输出文件的大小不会增长超出限制。我已经按照你的答案尝试过。
cd /var/abc
for file in $(ls -p | grep -v / | tail -1000); do cat "$file" >>"/var/abcd/xigzag"$tick".csv" && rm -rf "$file"; done
答案1
您不需要循环,您可以告诉cat
读取所有文件:
cat /var/abc/*.csv > file1.csv && rm /var/abc/*.csv
只要文件不是太多(但限制很大)。
在两个命令之间使用&&
可确保文件仅在成功“复制”时才被删除。
但有一些注意事项:
- 您不能在与要连接的原始文件相同的文件夹中运行此命令,否则将
rm
删除聚合,您将丢失所有内容; - 如果新的 CSV 文件出现在 的开始
cat
和 的参数扩展之间rm
,它们将被删除而不被复制; - 如果任何 CSV 文件在连接后被修改,这些修改将会丢失。
您可以通过在创建输出文件之前存储文件列表来缓解前两个警告:
set -- /var/abc/*.csv
cat -- "$@" > file1.csv && rm -- "$@"
复制文件后,这仍然会丢失对文件所做的任何更改。
要一次连接 1000 个文件(每 1000 个原始 CSV 生成一个 CSV)以及任意数量的文件,您可以在目标目录中按以下步骤操作:
find /var/abc -maxdepth 1 -type f -name \*.csv | split -d -l 1000 - csvlists
for file in csvlists*; do cat $(cat $file) > concat${file##csvlists}.csv && rm $(cat $file); done
/var/abc
这将找到named中的所有文件,并在以( , ...)*.csv
开头的文件中一次列出1000个文件。然后循环读取每个文件列表,并将列出的 CSV 文件连接到名为 etc. 的文件中以匹配列表。复制每组文件后,原始文件将被删除。csvlists
csvlists00
csvlists01
for
concat00.csv
此版本假定 CSV 文件的名称不包含空格、换行符等。
答案2
你的命令看起来几乎没问题。只需添加一个cat
and>>
即可实际附加内容:
for i in /var/abc/*.csv; do cat "$i" >> file1.csv && rm -rf "$i";done
我不太明白计数部分。你可以这样做:
let count=0
for i in /var/abc/*.csv; do
cat "$i" >> file1.csv && rm -rf "$i"
let count++
done
echo $count files processed.
答案3
和zsh
:
files=(/var/abc/*.csv(N.))
n=0
while (($#files)) {
cat $files[1,1000] > file$((++n)).csv &&
rm -f $files[1,1000] || break
files[1,1000]=()
}