【问题标题】:passing arguments to bash script using xargs使用 xargs 将参数传递给 bash 脚本
【发布时间】:2019-03-04 09:50:18
【问题描述】:

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

【问题讨论】:

    标签: bash xargs


    【解决方案1】:

    直接错误是传递给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.

    【讨论】:

    • 您的解决方案是我一开始想做的,但我有超过 500 万个文件,因此我尝试使用 xargs 运行它(最后我想在秒数中添加 -P N xargs)
    • 并行化受 I/O 限制的作业通常只会占用您的磁盘。
    【解决方案2】:

    我发现一次只做一件事并做好它会更容易。

    -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'
    

    【讨论】:

    • 最后一段假设您没有包含换行符的文件名。
    猜你喜欢
    • 2015-05-13
    • 1970-01-01
    • 2021-11-18
    • 2012-12-29
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多