首页 > 解决方案 > 使用 xargs 将参数传递给 bash 脚本

问题描述

我运行以下 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;'

标签: bashxargs

解决方案


直接错误是传递给的第一个参数以bash -c "...commands..."in 结尾$0,而不是 in $1"...commands..."此外,由于您在调用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并按其排序。

还要注意我们如何在私有变量中避免大写。


推荐阅读