我有一个名为DS1
. 我试图复制它 4 次,所以我也有DS2
,和.DS3
DS4
DS5
我可以从终端使用以下命令并且它可以工作:
for i in {2..5}; do cp -r /home/test/DS1 "DS$i"; done
但是,当我将它输入到这样的脚本中时:
#!/bin/sh
for i in {2..5}; do cp -r /home/test/DS1 "DS$i"; done
它创建一个名为DS{2..5}
的目录,而不是增量在 2 到 5 之间的目录。不明白我做错了什么。
{2..5}
是大括号扩展。POSIX未标准化大括号扩展。一些(但不是全部)广泛使用的Bourne 风格的shell 支持它。您在 Ubuntu 上的终端中与之交互的 shell 是
bash
,除非您故意使用不同的 shell。bash
支持大括号展开。但是你脚本上的shebangsh
是 for ,在 Ubuntu 上是一个符号链接到dash
.dash
不支持大括号扩展。所以你可以:
bash
脚本(或支持大括号扩展的其他 shell 的脚本,例如zsh
orksh
)。dash
.如果你想让你的脚本成为
bash
脚本,请替换和:
然后当像运行一样
./scriptname
运行时bash
。如果您通过编写来运行脚本,sh scriptname
那么您必须bash scriptname
改用它。如果要消除大括号扩展,有几种选择。我建议
seq
使用命令替换,这可能是大括号扩展的最常见替代方法,易于编写,并且可能被其他人类读者理解。代替
{2..5}
,你可以写$(seq 2 5)
。因为它没有被引用——也就是说,因为它是$(
)
而不是"$(
)"
——对结果执行字段拆分(bash
称为分词)。只要您没有将控制字段拆分的IFS
shell 变量设置为包含任何数字或不包含换行符的值,这将满足您的要求。(通配符——也称为文件名扩展,也称为路径名扩展——也对不带引号的命令替换的结果执行,但 的输出
seq
不会包含通配符?
,*
, 或[
,因此在这种情况下无效。)请注意,这
seq
不是POSIX标准化的。这几乎可以在任何 GNU/Linux 系统和一些其他类 Unix 操作系统上运行,但是seq
默认情况下没有安装一些类 Unix 操作系统(它们通常有jot
),因此不能保证在所有 Unix 上都可以运行-像操作系统。当您在终端中运行脚本时,您使用的 shell 很可能是 Bash。Bash 支持大括号扩展,因此
{2..5}
可以扩展为序列2 3 4 5
,并且您的脚本可以按预期工作。但是,当您将相同的 scipt 添加到文件时,它不起作用。这是由于您使用的shebang (
#!/bin/sh
),它告诉您的脚本在 sh shell 中运行,该 shell 符合 POSIX 并且不支持大括号扩展。所以你有两个选择:
#!/bin/bash
或另一个支持大括号扩展的 shell。或者
#!/bin/sh
并替换{2..5}
为$(seq 2 5)
。另请查看有关sh 和 Bash 之间差异的这个有趣的 Stack Overflow 问题。