连接文件夹中的大量文件时,参数列表太长

时间:2014-05-13 09:37:59

标签: linux shell unix sed

这是一个将多个相同模式文件连接成一个大文件的命令。在文件夹中我有77k文件,我得到Argument list too long

示例文件名是每分钟:cartreset-2014-05-08-01-12.log

rm -f /tmp/temp.files
ls -1 /var/log/processing/*.log | \
    xargs -n1 basename > /tmp/temp.files
cat /tmp/temp.files | \
    sed -r "s~(.*)-[0-9]{4}(-[0-9]{2})+\.log~cat /var/log/processing/\1* >> /var/log/processing/\1$(date  +"-%Y-%m-%d-%H-%M").log~" | \
    uniq | \
    sh
cd /var/log/processing
xargs rm -rf < /tmp/temp.files
rm -f /tmp/temp.files

sh: /bin/ls: Argument list too long

我有哪些选择?

3 个答案:

答案 0 :(得分:4)

您的完整代码是:

rm -f /tmp/temp.files
ls -1 /var/log/processing/*.log | xargs -n1 basename > /tmp/temp.files
cat /tmp/temp.files | sed -r "s~(.*)-[0-9]{4}(-[0-9]{2})+\.log~cat /var/log/processing/\1* >> /var/log/processing/\1$(date  +"-%Y-%m-%d-%H-%M").log~" | uniq | sh
cd /var/log/processing
xargs rm -rf < /tmp/temp.files
rm -f /tmp/temp.files

但问题出在ls -1 /var/log/processing/*.log部分,所以我正在跳过剩下的部分。

/var/log/processing/*.log完成的扩展会产生如此多的结果,ls本身无法处理所有这些结果,因此会打印&#34;参数列表太长&#34;消息。

您可以使用find语句,如下所示:

find /var/log/processing -name "*.log" -exec basename {} \; > /tmp/temp.files

请参阅我没有使用ls解析(阅读有趣的Why you shouldn't parse the output of ls)。

答案 1 :(得分:2)

ls的解析输出为always wrong

无论如何,问题是模式扩展到如此多的文件,超出了命令行的最大允许长度。有两种方法可以避免它:

  1. 使用for循环。 for循环中模式的扩展由shell内部处理,因此不受命令行长度的限制:

    for file in /var/log/processing/*.log
    do
        basename "$file"
    done > /tmp/temp.files
    

    (是的,整个循环的输出可以在done关键字后重定向) 使用xargs运行-n1时,使用循环效率会更高一些。

  2. 使用find

    find /var/log/processing \
        -maxdepth 1 -name '*.log' \
        -printf '%f\n' > /tmp/temp.files
    

    '%f'只打印文件名,因此可以节省您调用basename的权限。 -maxdepth就在那里,所以命令实际上等同于模式;如果没有子目录,则可以跳过它。另一方面,如果子目录,您可能需要使用%P,它会为您提供第一个参数(/var/log/processing)的相对路径。

  3. 我可能会尝试完全摆脱临时文件并在一个或多个循环中完成工作。

答案 2 :(得分:2)

删除临时文件,可以使用bash数组:

cd /var/log/processing

logs=( *.log )
prefixes=( "${logs[@]/-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9].log/}" )

date=$(date "+%Y-%m-%d-%H-%M")

printf "%s\n" "${prefixes[@]}" | 
sort -u |
while read -r prefix; do
    cat "$prefix"* >> "$prefix"-"$date".log
done 

printf "%s\n" "${logs[@]}" | xargs rm

cd -