Bash 对于目录中的大量文件,Shell脚本失败

Bash 对于目录中的大量文件,Shell脚本失败,bash,sh,Bash,Sh,操作系统:aix,shell:bsh 我在一个目录中有大约20k个文件,这些文件名为filename.pdf.marker和filename.pdf,我们用以下代码段复制目录内容 ls ${WORKING_DIR}/*.pdf.marker 2> /dev/null | while read FILEMARKER; do FILENAME=${WORKING_DIR}/$(basename ${FILEMARKER} .marker) mv ${FILENAME}

操作系统:aix,shell:bsh

我在一个目录中有大约20k个文件,这些文件名为filename.pdf.marker和filename.pdf,我们用以下代码段复制目录内容

ls ${WORKING_DIR}/*.pdf.marker 2> /dev/null | while read FILEMARKER;
do
    FILENAME=${WORKING_DIR}/$(basename ${FILEMARKER} .marker)
        mv ${FILENAME} ${LOG_DIR}/.  
        mv ${FILENAME}.marker ${LOG_DIR}/.  
    done   
但问题是并非所有文件都被复制,因为ls不会返回工作目录中的完整文件列表,因为文件列表太长

你能给我一些建议如何升级脚本而不删除循环吗


thx

改用外壳球。例如:

for file in ${WORKING_DIR}/*.pdf.marker; do
    : # do something with "$file"
done

如果文件列表太长,全局将失败。过滤结果,而不是全局:

ls ${WORKING_DIR} | grep '\.pdf\.marker$'  | while read FILEMARKER
do
    ...
done

强制性免责声明:如果您的文件名包含特殊字符,如任何空格,则此操作将失败。

尝试关闭
ls
-f
-U
,我认为),或使用另一个程序,如
查找尝试
查找
,而不是
查找

find ${WORKING_DIR} -name \*.pdf.marker | while read FILENAME; do
  ...
done

为了简单起见,我故意忽略了在文件名中使用空格的可能性。

我不想从CodeGnome那里窃取正确的答案,但要弄清楚会发生什么:
ls“$WORKING\u DIR”/*.pdf.marker
导致新进程的shell分叉,进程映像
ls
提供了#num_matching_files参数(与Windows不同,Windows上的每个命令都必须包含自己的全局代码,Unix上的全局在调用命令之前由shell展开)


大多数(如果不是所有的话)系统在命令行的长度/参数的数量上都有限制,而你在这里遇到了一道难题(因为在你的例子中,匹配文件的数量是20000个)

情况可能会更糟,因为shell globs通常会将整个列表读取到内存中,这通常比通过管道懒洋洋地读取要好,这比联合例程更不可预测,更容易出错。对于唯一正确的帖子,20000个文件名大约是+1。(但最好引用
${WORKING_DIR}
)@JoSo同意引用很重要,但这是手头问题的一个次要问题。(联合国)引用glob可能是一件丑陋的事情;最好的解决方案通常更像
cd“$WORKING\u DIR”;对于*标记中的文件;do:;完成
。同样的想法,但它避免引用比OP在这里处理的问题更复杂的glob模式(例如
foo*bar*.baz
)。感谢您提醒人们时刻关注防御性编码技术@CodeGnome:你可以简单地做
“$WORKING\u DIR”/*.pdf.marker
,这没有问题。-1为什么你一直声称globs可能会在没有给出参数的情况下失败?我没人知道我能找到这方面的迹象,除了你没有人声称。我刚刚测试了tmpfs和ext3目录中的1.000.000个文件,效果非常好。尝试
mkdirtestdir;cd testdir;对于'seq 1000'中的i;不要触摸'seq'$((i-1))“000”$i“000”;完成;我的时间到了;做回显“$i”;done | wc-l
(你必须触摸1000个文件1000次,因为我的系统中有1次1000000个文件:参数列表太长)@JoSo,因为我看到了这种情况。你为什么坚持否认地球仪会失败?@JoSo完全有可能,现代系统上的现代外壳的性能比过去要好得多。然而,就在2005年,我看到csh脚本在*
中出现
fori的错误,而globfailed的错误只有200000个文件。我不记得在伯恩贝壳里见过它。也许这只是一个csh错误。猜猜看,我已经做了,没有任何迹象表明glob会失败。(只有一些perl代码错误为“glob failed”,因为可能没有匹配的文件。但我们不是在讨论perl,每个人都知道任何类型的glob都可能无法匹配)。此外,任何规范都不允许出现错误。此外,它还可以处理1000.000个文件。请复制您声称存在的错误,并给出shell代码,我会告诉您它有什么问题。表示没有匹配的文件。在这种情况下,glob将扩展到自身(除非bash中的
shopt-s nullglob
),并且
ls
将告诉您没有这样的文件。我们知道这是可能发生的。这与您所声称的无关。问题不在于
ls
本身,而在于调用
ls
时使用了20000个参数,这太依赖于系统。这与OP遇到的问题相同:find命令的参数太多。您想要的是
-name\*.pdf.marker
,以防止参数被解释为glob并扩展到20000个参数。此外,正如您所指出的,在其他方面稍有不正确(不需要“简单”,甚至还有更简单的方法是正确的)