我有一个在 bash 4.3 中运行并检查 rpm 包的脚本。我希望相同的脚本能够在 bash 4.4 上成功运行,但该脚本会抛出警告“warning: command substitution: ignored null byte in input”
。下面是抛出此警告的行:
FIND_RPM=find /opt/RPM/components -type d -name enum-1.1.6 -print0
该脚本在调试模式下执行,如下所示:
+++ find /opt/RPM/components -type d -name eum-1.1.6 -print0
bash: warning: command substitution: ignored null byte in input
++ LINSEE_RPM=/opt/RPM/components/enum-1.1.6
我现在应该如何重写这一行以忽略此警告并像 bash4.3 中那样默默地删除此空字节?
答案1
由于您没有使用\0
该选项-print0
生成的字节,您可能需要:
FIND_RPM="$(find /opt/RPM/components -type d -name enum-1.1.6 -print)"
答案2
顺便说一句,如果出于某种原因您需要保留-print0
find 选项(即您希望结果包含新行),您可以在 bash 4.4 中使用不同的方法来执行此操作并避免结果串联。当将其分配给变量时,Bash 会抱怨空字节,但进程替换时的空字节处理没有问题。
如果您期望多个结果,您很可能需要一个数组:
$ IFS= readarray -t -d '' array < <(find . -type f -name 'a*.sh' -print0)
$ declare -p array
declare -a array=([0]="./appslist.sh" [1]="./advfind2.sh" [2]="./autorotate.sh" [3]="./autorot.sh" [4]="./advfind.sh" [5]="./appslist(draft).sh")
如果您只期望一个结果:
$ IFS= read -r -d '' var < <(find . -type f -name 'autorot.sh' -print0)
$ declare -p var
declare -- var="./autorot.sh"
仅供记录,此空字节删除行为不适用于其他 shell,例如zsh
.zsh
即使有多个结果,您的命令也可以-print0
毫无问题地工作。
zsh$ var=$(find . -type f -name 'auto*.sh' -print0)
zsh$ declare -p var
typeset var=$'./autorotate.sh\C-@./autorot.sh\C-@'
zsh$ echo "$var" |od -w32 -t x1c
0000000 2e 2f 61 75 74 6f 72 6f 74 61 74 65 2e 73 68 00 2e 2f 61 75 74 6f 72 6f 74 2e 73 68 00 0a
. / a u t o r o t a t e . s h \0 . / a u t o r o t . s h \0 \n
答案3
您的命令将保持不变(即使您的问题中的语法无效,可能是复制粘贴问题),并且在 bash 4.3 和 bash 4.4 中的工作方式相同。
空字节仍然被丢弃,唯一的不同是警告消息,它被添加到bash 4.4 补丁 2
在您的情况下,该命令有效,因为它只找到一个条目。如果找到多个条目,那么它们将被连接在一起(因为空字节被删除)。
将命令更改为:
FIND_RPM=$(find /opt/RPM/components -type d -name enum-1.1.6)
修复该问题,但如果任何路径包含换行符,仍然会阻塞。
答案4
FIND_RPM=find /opt/RPM/components -type d -name enum-1.1.6 -print0
可能应该是
FIND_RPM=$(find /opt/RPM/components -type d -name enum-1.1.6 -print0)
但这不是警告消息的原因。
您使用-print0
withfind
将会输出一个 nul 字节($'\0'
,ASCII 0)作为 找到的路径之间的分隔符,find
而不是由 生成的通常换行符-print
(没有零)。
通常用来-print0
发送路径可能包含空格或其他空白字符xargs
或其他知道如何处理空字节终止路径的实用程序。这样可以正确处理路径中的外来文件名(nul 字节可能不是 Unix 上文件名的一部分,但空格或换行符可能是)。
就你而言,我认为这只是更改-print0
为 的问题-print
。
在找到多个路径的情况下,这还具有为您提供有效路径的效果。使用-print0
,Bash 会删除 nul 并连接路径。