【问题标题】:POSIX-compliant shell equivalent to Bash "while read -d $'\0' ..."?POSIX-compliant shell 等价于 Bash “while read -d $'\0' ...”?
【发布时间】:2016-05-20 09:21:30
【问题描述】:

我正在尝试使 Bash 脚本严格符合 POSIX,即使用 checkbashisms -px ${script_filename} 删除任何潜在的“Bashisms”。在给定的文件中,我使用find 遍历一个目录,然后使用\0 作为分隔符,使用-print0 将每个文件路径传送到read,以便能够处理包含换行符的文件名:

find . -print0 | while read -d $'\0' inpath
do
    echo "Reading path \"${inpath}\"."
done

但是,checkbashisms 不喜欢这个,因为the option -d isn't strictly POSIX-compliant

...行 n 中可能存在的 bashism(使用 -r 以外的选项读取)

如何编写符合 POSIX 的等效代码,即使用非换行符从 find 读取输出?

【问题讨论】:

    标签: bash shell find pipe sh


    【解决方案1】:

    如果没有-d 选项,read 内置函数无法读取以空值结尾的数据。

    你可以在find + xargs

    find . -mindepth 1 -print0 | xargs -0 sh -c 'for f; do echo "Reading path \"$f\""; done' _
    

    或者,如果您不介意为每个文件生成一个 shell,请使用 find

    find . -mindepth 1 -exec sh -c 'echo "Reading path \"$1\""' - {} \;
    

    【讨论】:

    • 第一个建议将设置$0, $1, ... ${!#} 所以for f;读取第一个传递的值。您可以通过向 sh 发送一个空参数来解决此问题:find ... | xargs -0 sh -c '...' ""
    • 实际上我已经在 2 个不同的系统上测试了该命令,find . -print0 | xargs -0 sh -c 'echo "$@"' 确实打印了所有文件名。
    • 我认为这是因为第一个是当前目录。但是使用像 -type f 这样的过滤器,您会发现不同。
    • 是的,你是正确的,非常感谢(用-mindepth 1编辑了答案)
    • 您实际上不需要生成单独的外壳;例如,find . -mindepth 1 -exec /bin/echo "Reading path \"{}\"" 也可以。
    猜你喜欢
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2017-08-31
    • 2012-08-23
    • 2010-10-22
    • 1970-01-01
    相关资源
    最近更新 更多