我正在运行一个基于文件的选项/参数的命令。所以我 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
它。(如果您想检查文件的内容,只需相应地扩充脚本,或者在需要时寻求帮助。)然后代码循环遍历文件驱动的参数。如果文件只包含一个单词,则将选项和值添加到数组中;否则,跳过参数。循环后,我们添加选项,并执行命令。kernel
ramdisk
dtb
cmdline
boot.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 …
。