0

关于这个主题已经有一些答案,但几乎所有人都说解析 的输出很糟糕ls -l,因此建议使用其他方法。

但是,我正在使用ncftpls -l,因此我不能使用 shell glob 之类的东西,或者find– 我认为我确实需要实际解析ls -l输出。如果您不熟悉ncftpls,请不要担心,输出返回的格式与您刚刚使用 的格式完全相同ls -l

在公共远程 ftp 目录中有一个文件列表,我不想在每次我的 cronjob 触发时重新下载每个所需的文件来加重远程服务器的负担。我想检查,对于 ftp 目录中的每个文件子集,该文件是否在本地存在;如果没有,请下载它。

这很容易,我只是使用

tdy=`date -u '+%Y%m%d'`_

# Today's files
for i in $(ncftpls 'ftp://theftpserver/path/to/files' | grep ${tdy}); do
    if [ ! -f $i ]; then
        ncftpget "ftp://theftpserver/path/to/files/${i}"
    fi
done

但是我遇到了一个问题,有时 cron 作业会下载一个尚未完成上传的文件,因此当它下次触发时,它会跳过部分下载的文件。

所以我想添加一个检查,以确保对于我已经拥有的每个文件,本地文件大小与远程服务器上相同文件的大小相匹配。

我在考虑解析ncftpls -l和使用awk的输出,比如

for i in $(ncftpls -l 'ftp://theftpserver/path/to/files' | awk '{print $9, $5}'); do
    ...
    x=filesize   # somehow get the file size and the filename
    y=filename   # from $i on each iteration and store in variables
    ...
done

但我似乎无法在循环的同一迭代中将文件名和文件大小从服务器获取到局部变量中;每次迭代时,$i 在 awk 字符串中的 $9 和 $5 之间交替。

如果我能设法在每次迭代中将文件名和文件大小放入单独的变量中,我可以简单地使用stat -c "%s" $i来获取本地大小并将其与远程大小进行比较。然后它对ncftpget我还没有的每个远程文件都很简单。我也对同步程序进行lftp了修改,但运气不佳,宁愿这样做。

任何帮助表示赞赏!

4

1 回答 1

1

for 循环在看到任何空格(如空格、制表符或换行符)时会拆分。所以,在循环之前需要 IFS,(有很多关于......的问题)

IFS=$'\n' && for i in $(ncftpls -l 'ftp://theftpserver/path/to/files' | awk '{print $9, $5}'); do

echo $i | awk '{print $NF}' # filesize 
echo $i | awk '{NF--; print}' # filename
# you may have spaces in filenames, so is better to use last column for awk

done

我认为更好的方法是使用而不是使用,所以

ls -l | while read i
do
echo $i | awk '{print $9, $5}'

#split them if you want 
x=echo $i | awk '{print $5}'
y=echo $i | awk '{print $9}'

done
于 2019-07-10T15:10:02.173 回答