不能 运行 通过 ssh 连接在脚本命令中循环

Can't run for loops inside script command over ssh conection

我正在尝试 运行 使用命令后的 for 循环

script

将命令终端副本输出到 txt 文件(以供进一步检查)。 这一切都是通过 solar-putty 上的 SSH 连接完成的。

这是我的代码:

filename=$(ls /home/*.txt  | xargs -n1 -I{} basename "{}" | head -3) 
echo "$filename"
script /home/test.txt
for f in $filename; do
        echo $f; done
exit

这不会启动 for 循环。上面的命令就直接登录了,我执行不了

当我运行:

for f in $filename; do
        echo $f; done

一切正常...

我在 TMUX 终端内使用所有这些作为 sudo su(因为我害怕通过 SSH 丢失我的终端,我需要 sudo su)

如果我明白你在做什么,问题是 script 正在启动一个新的 shell(作为子进程),并且它没有旧的(父进程) shell的变量。能不能定义变量afterstartingscript,所以定义在右边shell?

另一种可能的解决方案是 export 变量,将其从 shell 变量转换为环境变量,子进程将继承它的副本。请注意,根据您使用的shell,您可能需要双引号分配的值以避免分词问题:

export filename="$(ls /home/*.txt  | xargs -n1 -I{} basename "{}" | head -3)"

顺便说一句,这种处理文件名列表的方式会 运行 遇到带有空格或其他一些 shell 元字符的名称的麻烦。处理文件名列表的正确方法是将它们存储为数组,但遗憾的是无法导出数组。

[编辑:] 带有空格 and/or 其他奇怪字符的文件名的问题是 1) ls 输出文件名的方式不明确且不一致,以及 2) shell "不带引号的变量上的分词”可以以……不幸的……方式解析文件名列表。举一个极端的例子,假设您有一个名为 /home/this * that.txt 的文件——如果它在一个变量中,并且您使用的变量周围没有双引号,它将处理 /home/thisthat.txt 作为完全独立的东西,它还会将 * 扩展到当前目录中的文件名列表中。请参阅 this question from yesterday,了解此类真实发生的众多示例之一。

为了安全地处理带有奇怪字符的文件名,基本规则是获取文件列表时使用原始 shell 通配符(不是 ls!)或 find-exec-print0,始终将文件名列表存储在数组中(不是普通变量),并双引号所有变量 (/array) 引用。参见 BashFAQ #20: "How can I find and safely handle file names containing newlines, spaces or both?"

在这种情况下,您只需要使用通配符表达式来创建一个路径数组,然后 shell 的内置字符串操作来删除路径前缀:

filepaths=( /home/*.txt )    # Create array of matching files
filenames=( "${filepaths[@]##*/}" )    # Remove path prefixes

然后您可以使用 "${filenames[@]:0:3}" 从数组中获取前三个名称。您可以只用前三个文件创建一个新数组,也可以直接在循环中使用它:

first3files=( "${filenames[@]:0:3}" )    # ...or...
for f in "${filenames[@]:0:3}"; do
    echo "$f"    # Always double-quote variable references!
done

请注意,bash 不允许堆叠大多数 array/variable 修饰符,因此获取路径数组、去除前缀和仅选择前几个必须作为三个单独的步骤完成.