在Bash中的for循环中只运行一次命令



我有以下函数中的bash代码模式:

for folder in ${FOLDER[@]}; do
if [ $# -ne 0 ]; then
rsync -rvh --delete-after ${folder} ${folder_dest}
else
local zipFile=$(stamp-files file.zip)
unzip -q ${zipFile} "${folder}"*  -d "${folder_src}"
rsync -rvh --delete-after ${folder_src}${folder} ${folder_dest}
rsync -rvh --delete-after ${folder_src}${folder} ${folder_dest2}
fi
done

因此,在这个函数中,我在for循环中有一个if语句。正如您在其他部分中看到的,有一个对另一个函数stamp-files的调用。仅在第一次迭代中就需要对其他函数的调用,即使它没有引起任何问题,也可以通过只调用一次来进行改进。

你知道我如何简单地做到这一点并保持代码的形状(for循环中的if语句(吗?

您可以设置一个变量并在第一次迭代中更改它:

first='yes'
for folder in "{folders[@]}"; do
if [[ $first == 'yes' ]]; then
local files=$(stamp-files "$folder")
rsync -rvh --delete-after "$files" "$folder_dest"
first='no'
else
rsync -rvh --delete-after "$folder" "$folder_dest"
fi
done

尝试使用$#的方式不起作用:这是位置参数的数量,与迭代次数或类似情况无关。

我还改变了一些事情:

  • folders而不是FOLDER;大写的变量名更有可能与shell和环境变量发生冲突
  • 引用所有扩展名以防止单词拆分和globbing([[...]]中的左侧自动引用(
  • 我用的是$folder而不是${folder},但这只是个人品味

如果您需要保留for循环的结构和内部If:

unset stamp_files_done
for folder in ${FOLDER[@]}; do
if [ $# -ne 0 ]; then
rsync -rvh --delete-after ${folder} ${folder_dest}
else
if [[ -z ${stamp_files_done+x} ]]; then local files=$(stamp-files ${folder}); stamp_files_done=""; fi
rsync -rvh --delete-after ${files} ${folder_dest}
fi
done

您还可以解释整个任务以获得更准确的解决方案。

我知道你说过你想保持代码的形状,但从风格上讲,我总是犹豫是否在循环中使用if来构建代码,只是为了处理数组的第一个元素——我更喜欢把代码吊出来,以强调第一个元素受到了特殊处理。另一种选择是添加一个状态变量,这永远不会让代码变得更清晰。

在你的情况下,怎么样

if [ ${#FOLDER[@]} -ne 0 ]; then
local files=$(stamp-files ${FOLDER[0]})
rsync -rvh --delete-after ${files} ${folder_dest}
for folder in ${FOLDER[@]:1}; do
rsync -rvh --delete-after ${folder} ${folder_dest}
done
fi

最新更新