【问题标题】:Heredoc commands for find . -exec sh {} +用于 find 的 Heredoc 命令。 -exec sh {} +
【发布时间】:2018-09-13 12:43:42
【问题描述】:

我正在尝试将 TIFF 图像文件的层次结构转换为 JPG,出于无聊,我想在一个文件中执行 findffmpeg

所以我将find 设置为使用-s 标志调用sh,就像变薄一样:

#!/bin/sh
export IFS=""

find "$@" -iname 'PROC????.tif' -exec sh -s {} + << \EOF
for t ; do 
ffmpeg -y -v quiet -i $t -c:v mjpeg ${t%.*}.jpg
rm $t
done
EOF

但是,目录层次结构中的文件太多了,并且找到了切碎的文件名数组,分成了几个小块,并且 sh -s 仅成功调用了第一个参数块。

问题是:如何将这样的体内命令提供给find 命令中的每个sh 调用?

更新

问题上的标签“heredoc”旨在接收不依赖外部文件或通过$0自引用的答案。它还旨在使任何文件名都不会经过字符串数组处理,例如使用 NUL 终止符或换行符填充,并且可以直接作为参数传递。

【问题讨论】:

    标签: loops sh heredoc


    【解决方案1】:

    我在下面重写你的代码:-

    #!/bin/bash
    
    find "$1" -name "PROC????.tif" > /tmp/imagefile_list.txt
    while read filepath
    do
        path=${filepath%/*}
        imgfile=${filepath##*/}
        jpgFile=${imgfile%.*}.jpg
        cd "$path"
        ffmpeg -y -v quiet -i "$imgfile" -c:v mjpeg "$jpgFile"
        rm -rf $imgfile
    done < /tmp/imagefile_list.txt
    

    如果你不想改变当前目录,你可以像下面这样:-

    #!/bin/bash
    
    find "$1" -name "PROC????.tif" > /tmp/imagefile_list.txt
    # If you list down all the .tif file use below command
    # find "$1" -name "*.tif" > /tmp/imagefile_list.txt
    while read filepath
    do
        path=${filepath%/*}
        imgfile=${filepath##*/}
        jpgFile=$path${imgfile%.*}.jpg
        ffmpeg -y -v quiet -i "$filepath" -c:v mjpeg "$jpgFile"
        rm -rf $imgfile
    done < /tmp/imagefile_list.txt
    
    rm -rf /tmp/imagefile_list.txt
    

    【讨论】:

    • 程序假设 imagefile_list.txt 不会作为重要的东西存在于当前工作目录中。
    • 不太了解你。 imagefile_list.txt您的脚本无法生成此文件?
    • 是的。我很清楚 sh 对 -c 标志的作用,将 -s 与heredoc一起使用的全部目的是为了更好地格式化。并且将列表保存到 txt 文件可以并且应该已经替换为管道。
    • 另外,path=${filepath%/*},你怎么能确定 $filepath 不是相对路径?我没有在我的代码中做出这样的假设。
    • 尝试在/tmp/imagefile_list.txt中创建。只需检查它是否适合您。我只是想在这里帮助你。如果没有帮助,我将删除我的答案。
    【解决方案2】:

    heredoc 被用作查找的输入。我认为你最好的选择是根本不使用heredoc,而只使用一个字符串:

    #!/bin/sh
    find "$@" -iname 'PROC????.tif' -exec sh -c '
    for t ; do 
    ffmpeg -y -v quiet -i "$t" -c:v mjpeg "${t%.*}.jpg" &&
    rm "$t"
    done
    ' sh {} +
    

    【讨论】:

    • 这正是我回到办公室时所做的。您能否通过解释为什么您认为我应该使用双引号而不是设置 IFS="" 来添加樱桃顶部?
    • 一般来说,我认为将 IFS 设置为相当脆弱并尽量避免它。因为它似乎对这个问题并不重要,我认为删除它会澄清答案。添加双引号更多的是为了演示最佳实践。
    • 一般来说,将IFS 设置为空字符串是不够的,因为不带引号的参数扩展仍然会受到路径名扩展的影响,而不仅仅是分词。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 2013-01-13
    • 2015-02-17
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多