使用 --my_argument `cat some_file` 作为某些命令的参数

使用 --my_argument `cat some_file` 作为某些命令的参数

我正在运行一个基于文件的选项/参数的命令。所以我 cat在命令中输入了文件。但是,当文件中没有任何内容时,这就有问题了。

mkbootimg --kernel "$SCRIPT_DIR/devices/$DEVICE/kernel/k/arch/arm64/boot/Image" \
--ramdisk boot.img-ramdisk \
--dtb boot.img-dtb \
--cmdline "$(cat boot.img-cmdline)" \
--base `cat boot.img-base` \
--kernel_offset `cat boot.img-kernel_offset` \
--ramdisk_offset `cat boot.img-ramdisk_offset` \
--tags_offset `cat boot.img-tags_offset` \
--dtb_offset `cat boot.img-dtb_offset` \
--os_version `cat boot.img-os_version` \
--os_patch_level `cat boot.img-os_patch_level` \
--pagesize `cat boot.img-pagesize` \
--header_version `cat boot.img-header_version` \
--hashtype `cat boot.img-hashtype` \
--board `cat boot.img-board` \
--ramdisk_offset `cat boot.img-ramdisk_offset` \
-o ../boot.img)

例如,如果 中没有任何内容boot.img-board ,而 中没有“0x10000” boot.img-ramdisk_offset,那么

--board `cat boot.img-board` \
--ramdisk_offset `cat boot.img-ramdisk_offset` \

--board   --ramdisk_offset 0x10000

因此它认为是board--ramdisk_offset 然后将其解释0x10000为另一个论据mkbootimg

我想--board 只在文件中有内容时才执行boot.img-board。如果文件中没有任何内容,我想不传递参数,而是继续执行没有参数的命令。解决这个问题的最佳方法是什么?

(文件中永远不会包含两个或更多个单词。)

答案1

构建于Hannu 的回答但是如果……怎么办?,因为你已指定

args=(
        --kernel "$SCRIPT_DIR/devices/$DEVICE/kernel/k/arch/arm64/boot/Image"
        --ramdisk boot.img-ramdisk
        --dtb boot.img-dtb
        --cmdline "$(cat boot.img-cmdline)"
)
for param in base kernel_offset ramdisk_offset tags_offset dtb_offset os_version \
            os_patch_level pagesize header_version hashtype board ramdisk_offset
do
        f="boot.img-$param"
        if [ "$(wc -w < "$f")" = 1 ]
        then
                args+=("--$param" "$(cat "$f")")
        else
                printf 'Problem with %s.\n' "$f"
        fi
done
args+=(-o ../boot.img)
mkbootimg "${args[@]}"

感谢您对文件进行一致的命名;这使得工作变得更容易。

这将创建一个名为 的数组,并使用固定参数( 、 和 )启动args它。(如果您想检查文件的内容,只需相应地扩充脚本,或者在需要时寻求帮助。)然后代码循环遍历文件驱动的参数。如果文件只包含一个单词,则将选项和值添加到数组中;否则,跳过参数。循环后,我们添加选项,并执行命令。kernelramdiskdtbcmdlineboot.img-cmdline-o

笔记:

  • 我非常忠实地复制了你的代码,甚至包含ramdisk_offset两次,尽管我怀疑那是一个打字错误。

  • 我 出于本网站其他地方讨论过的原因将其改为`…`等效的。$(…)

  • 我已经编写了代码来处理仅包含以下内容的文件确切地一个单词。如果您决定/意识到您的文件可能包含多个单词,则必须更改代码。

  • 如果需要,您可以在这个多行结构中包含反斜杠:

    args=( \
            --kernel "$SCRIPT_DIR/devices/$DEVICE/kernel/k/arch/arm64/boot/Image" \
            --ramdisk boot.img-ramdisk \
            --dtb boot.img-dtb \
            --cmdline "$(cat boot.img-cmdline)" \
    )
    

    但你不需要。当 shell 看到 时(,它知道它必须继续读取,直到看到匹配的)

  • 此外,如果您愿意,您可以在一行上放置多个选项:

    args=(--kernel "$SCRIPT_DIR/devices/$DEVICE/kernel/k/arch/arm64/boot/Image"
          --ramdisk boot.img-ramdisk --dtb boot.img-dtb --cmdline "$(cat boot.img-cmdline)")
    
  • 为了便于阅读和编辑,您可能需要在单独的行上列出参数:

    for param in \
            base \
            kernel_offset \
            ramdisk_offset \
            tags_offset \
            dtb_offset \
            os_version \
            os_patch_level \
            pagesize \
            header_version \
            hashtype \
            board \
            ramdisk_offset
    do
    
  • 这必须在 bash 中运行。

    • 如果你以笨拙的方式运行脚本,你必须说bash script.sh。如果你说sh script.sh,你正在运行默认 shell ( /bin/sh),它可能符合 POSIX 标准,但可能不是 bash,并且可能不支持数组。
    • 如果你将它作为可执行脚本运行(执行chmod +x然后以 运行./script.sh),则必须以“shebang”开头
      #!/bin/bash
      
      或者
      #!/usr/bin/env bash
      
      这必须是脚本的第一行。

    PS 实际上,如果你不能使用 bash,还有一个替代方案。请参阅这里

答案2

简单的答案:

if [ $( cat boot.img-board | tr '\n' '\x20' | wc -w ) -gt 0 ] ;then
  # do your thing
else 
  echo "We have no data to process...\b"
fi

# UNTESTED

其含义很简单:检查文件中是否有任何“单词”,如果有,则启动该进程,否则仅告知事实。

检查:读取文件,用空格替换所有 NEWLINE 字符(全部放在一行),并测试结果中是否还有空格以外的内容。

理解 Bash,更多内容
www.tldp.org,查找并阅读 Bash 指南。

答案3

您已标记,所以我会毫不犹豫地使用 Bash 特定的语法。

一种可靠的方法是将命令(或至少参数)构建为数组。您可以向数组中添加有条件的。 例子:

#!/bin/bash

unset arr
arr=(--ramdisk boot.img-ramdisk)
arr+=(--dtb boot.img-dtb)
arr+=(--option 'value    with     spaces')
# etc.

# essence begins
value=$(<boot.img-board)
if [ "$value" ]; then
   arr+=(--board "$value")
fi
# essence ends

arr+=('final argument')
printf '<%s>\n' "${arr[@]}"

构建正确数组后,使用mkbootimg "${arr[@]}"而不是printf …

相关内容