这是一个将多个相同模式文件连接成一个大文件的命令。在文件夹中我有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
我有哪些选择?
答案 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。
无论如何,问题是模式扩展到如此多的文件,超出了命令行的最大允许长度。有两种方法可以避免它:
使用for
循环。 for循环中模式的扩展由shell内部处理,因此不受命令行长度的限制:
for file in /var/log/processing/*.log
do
basename "$file"
done > /tmp/temp.files
(是的,整个循环的输出可以在done
关键字后重定向)
使用xargs
运行-n1
时,使用循环效率会更高一些。
使用find
:
find /var/log/processing \
-maxdepth 1 -name '*.log' \
-printf '%f\n' > /tmp/temp.files
'%f'
只打印文件名,因此可以节省您调用basename
的权限。 -maxdepth
就在那里,所以命令实际上等同于模式;如果没有子目录,则可以跳过它。另一方面,如果是子目录,您可能需要使用%P
,它会为您提供第一个参数(/var/log/processing
)的相对路径。
我可能会尝试完全摆脱临时文件并在一个或多个循环中完成工作。
答案 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 -