2012-07-06 149 views
1

操作系统:AIX,外壳:BSHshell脚本未能在目录

我已经在目录中的文件和这些文件的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

回答

4

改为使用shell glob。例如:

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

这将有可能更糟,因为外壳球通常将整个列表读入内存 – fork0 2012-07-06 13:23:06

+1

,这通常比通过管道懒惰地执行更好,这比共例程更加不可预测且容易出错。考虑到这是一种极端情况,20000个文件名将大致<1M的内存。 – 2012-07-06 14:03:02

+1

+1为唯一正确的帖子。 (但最好引用'$ {WORKING_DIR}')。 – 2012-07-06 14:31:24

-1

如果文件列表太长,globs会失败。结果如下:

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

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

+0

-1为什么你会一直声称,如果没有提供论据,球体就会失败?我没有一个规格说明我可以找到这个指标,除了你声称没有人。我刚刚在tmpfs和ext3目录中测试了1.000.000个文件,就像一个魅力。试试'mkdir testdir; cd testdir;因为我在\ seq 1000 \';请触摸\“seq”$((i-1))“000”$ i“000 \';完成;我在*的时间;做回声“$我”;完成| wc -l'(你必须1000次触摸1000个文件,因为1次1000000个文件:我的系统上的参数列表太长) – 2012-07-06 14:26:21

+0

@JoSo因为我看到它发生了。为什么你坚持否认球可能会失败? – 2012-07-06 14:33:44

+0

@JoSo Google“glob failed” – 2012-07-06 14:37:58

-2

尝试关闭排序为ls-f-U,我认为),或者使用其他程序一样find

+0

问题不在于'ls'本身,而是''ls'被20000个参数调用,这取决于系统太多。 – 2012-07-06 14:39:55

1

尝试find而不是ls

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

我故意忽略了文件名中有空格的可能性,以保持简单。

+1

这会遇到与OP一样的问题:find命令的参数过多。你想要的是'-name \ *。pdf.marker',以防止参数被解释为glob并扩展为20000个参数。此外,如您所指出的,其他方面略有不正确(不需要做“简单”,甚至有更简单的方法在上面是正确的) – 2012-07-06 14:45:00

0

我不想从CodeGnome偷正确答案的荣誉,但清楚发生了什么:ls "$WORKING_DIR"/*.pdf.marker导致新工艺的外壳分叉与设有#num_matching_files参数(不像在Windows上,进程映像ls,每一个命令必须包含自己的通配符代码,在Unix上,通过shell扩展了glob,甚至在该命令被调用之前)。

如果不是所有系统都限制为参数的命令行/数的长度,你只投中一硬墙这里(因为你的情况#num_matching_files 20000)