Bash 设置shell变量以包含文件列表
我使用下面的代码来设置一个包含一系列不同文件名的变量,随后我将对这些文件名执行一些函数。所涉及的文件位于与执行代码的目录(Bash 设置shell变量以包含文件列表,bash,shell,Bash,Shell,我使用下面的代码来设置一个包含一系列不同文件名的变量,随后我将对这些文件名执行一些函数。所涉及的文件位于与执行代码的目录(当前目录)不同的目录(当前目录)中。我认为可以使用下面的代码更改到包含文件的目录cd$directory,将文件列表存储在变量$files中,然后更改回原始目录(cd$CURRENT\u directory),在那里可以执行其余代码。但是,如果我执行两个echo命令,当我位于文件存储目录中时,第一个命令包含文件列表,但第二个echo命令只打印“vclist\u 2d\u*.t
当前目录
)不同的目录(当前目录
)中。我认为可以使用下面的代码更改到包含文件的目录cd$directory
,将文件列表存储在变量$files
中,然后更改回原始目录(cd$CURRENT\u directory
),在那里可以执行其余代码。但是,如果我执行两个echo命令,当我位于文件存储目录中时,第一个命令包含文件列表,但第二个echo命令只打印“vclist\u 2d\u*.txt”
,即它将其解释为字符串而不是文件列表(可能是因为我已更改回原始目录,因此它找不到任何与vclist\u 2d\u*.txt
匹配的文件)。为什么会发生这种情况,以及如何解决此问题(不在同一目录中运行所有内容)
您需要保存全局扩展的结果 glob不会在简单变量赋值中展开,因此当前代码在
echo
glob时会展开glob(这就是您看到的行为的原因)。例如,尝试echo“$FILES”
,它根本不会展开
但是,分配给数组时一定要展开,这样
FILES=(vclist_2d_*.txt)
将立即展开全局,然后使用echo“${FILES[@]}”
以后将正常工作。您需要保存全局展开的结果
glob不会在简单变量赋值中展开,因此当前代码在echo
glob时会展开glob(这就是您看到的行为的原因)。例如,尝试echo“$FILES”
,它根本不会展开
但是,分配给数组时,一定要展开。
FILES=(vclist\u 2d\u*.txt)
将立即展开全局,然后使用echo“${FILES[@]}”
以后将正常工作。FILES=vclist\u 2d\u*.txt
不会被shell展开。FILES
现在包含字符串vclist\u 2d\u*.txt
echo$FILES
向shell发送echo vclist_2d_*.txt
。然后shell展开模式,如果模式不匹配,则生成A)字符串vclist_2d_*.txt
,或者B)匹配文件名的列表
然后更改目录,并重复该过程。分配给任何变量的文件列表都不存在
现在,您可以将echo vclist\u 2d\u*.txt
的输出分配给一个变量(SOMEVAR=$(echo vclist\u 2d\u*.txt)
,但这只能解决一半的问题。您打算如何“对列表中的每个文件执行操作”如果您在$SOMEVAR <代码>中考虑文件<代码>,请考虑如果文件名包含空间…会发生什么?
最简单、最可靠的解决方案是使用find
代替:
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} +
这会导致do\u something
传递一个匹配文件列表。如果列表很长,可能会将其拆分为多个调用do\u something
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} \;
这将导致为每个匹配文件调用do\u something
如果当前目录可能包含与上面传递给
find
的模式相匹配的文件,则需要转义星号(通过像我一样添加引号,或通过\*
转义)为了避免shell扩展,请将find
命令转换为其他命令。FILES=vclist\u 2d\u*.txt
不会被shell扩展。FILES
现在包含字符串vclist\u 2d\u*.txt
echo$FILES
向shell发送echo vclist_2d_*.txt
。然后shell展开模式,如果模式不匹配,则生成A)字符串vclist_2d_*.txt
,或者B)匹配文件名的列表
然后更改目录,并重复该过程。分配给任何变量的文件列表都不存在
现在,您可以将echo vclist\u 2d\u*.txt
的输出分配给一个变量(SOMEVAR=$(echo vclist\u 2d\u*.txt)
,但这只能解决一半的问题。您打算如何“对列表中的每个文件执行操作”如果您在$SOMEVAR <代码>中考虑文件<代码>,请考虑如果文件名包含空间…会发生什么?
最简单、最可靠的解决方案是使用find
代替:
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} +
这会导致do\u something
传递一个匹配文件列表。如果列表很长,可能会将其拆分为多个调用do\u something
find $DIRECTORY -name "vclist_2d_*.txt" -exec do_something {} \;
这将导致为每个匹配文件调用do\u something
如果当前目录可能包含与上面传递给
find
的模式相匹配的文件,则需要转义星号(通过像我一样添加引号,或通过\*
转义)为了避免shell扩展,将您的find
命令转换为其他命令。我本来打算用FILES=$(echo…
)发布一个答案,但我更喜欢您的数组解决方案。您能解释一下为什么需要echo“${FILES[@]}”语法吗。这是数组中所有元素的扩展。比如“$@”
但是对于数组。不幸的是,我在bashref中没有看到关于这一点的好的简明部分(这很奇怪)。我本来打算用FILES=$(echo…
)发布一个答案,但是我更喜欢你的数组解决方案。你能解释一下为什么echo“${FILES[@}”
需要语法。这是数组中所有元素的扩展。如“$@”
但对于数组。Un