使用xargs将参数传递给bash脚本

时间:2019-03-04 09:50:19

标签: bash xargs

我运行以下bash命令来格式化带有文件inode和哈希的日志:

time find BASE_DIR -maxdepth 1 -mindepth 1 -type d |
sort |
xargs -P100 -n1 -IFF bash -ce "find FF -type f" |
sort |
xargs -n1 -I {} bash -ce "
    FILE=$1; INODE=`stat -c '%i' $FILE`;
    HASH=`cat $FILE | md5sum | cut -d' ' -f1`;
    printf 'Name: %s - Inode: 0x%X - MD5: %s\n' $FILE $INODE $HASH;" {}

但是,每次运行此命令,我都会得到类似的东西:

Name: FILE1 - Inode: 0xFFFFFFFFFFFFFFFF> - MD5: SOME_MD5
Name: FILE1 - Inode: 0xFFFFFFFFFFFFFFFF> - MD5: SOME_MD5
Name: FILE1 - Inode: 0xFFFFFFFFFFFFFFFF> - MD5: SOME_MD5
Name: FILE1 - Inode: 0xFFFFFFFFFFFFFFFF> - MD5: SOME_MD5

每次都相同的文件。如何正确将args传递给bash?

编辑
通过将第二个xargs更改为:

xargs -n1 bash -ce '
    path="$0";
    inode=`stat -c "%i" $path`;
    hash=`cat $path | md5sum | cut -d" " -f1`;
    printf "Name: %s - InodeContext<0x%X> - MD5: %s\n" $path $inode $hash;'

2 个答案:

答案 0 :(得分:3)

直接的错误是传递给bash -c "...commands..."的第一个参数以$0结尾,而不是以$1结尾。另外,由于您在"...commands..."周围使用了双引号,因此 calling shell将在脚本传递到子shell时对所有变量进行插值。

但是,这似乎确实令人费解。在不知道您确切希望完成什么的情况下,这是一种推测,但是我会采用类似的方式

time find BASE_DIR -maxdepth 1 -mindepth 1 -type d \
    -execdir find . -type f -exec bash -c '
        for f; do
            inode=$(stat -c "%i" "$f")
            md5=$(md5 <"$f" | cut -d " " -f1)
            printf "Name: %s - Inode: 0x%X - MD5: %s\n" "$f" "$inode" "$md5"
        done' _ {} \\+ \;

如果您可以解释如何对输出进行排序,则可以将排序键放在printf中,并在最后进行排序。

还请注意我们如何avoid uppercase in private variables.

答案 1 :(得分:0)

一次做一件事情并做好一件事情,我发现它更容易。

-I{}选项表示-n1。我仍然习惯使用与-i相同的-I{}选项。

find BASE_DIR -maxdepth 1 -mindepth 1 -type d |
# what's the point in sorting before -P100?
xargs -P100 -i find {} -type f |
sort |
# run stat and md5sum for the same file
# output: <filename> <stat output> <md5sum>
xargs -n1 bash -ce '
      printf "%s\n" "$1"; 
      stat -c "%i" "$1"; 
      md5sum "$1" | cut -d" " -f1;
' -- |
# for every three (filename, stat, md5sum) arguments run printf
xargs -n3 printf 'Name: %s - Inode: 0x%X - MD5: %s\n'