我的脚本:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
这是错误:
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
我究竟做错了什么?
答案1
编辑前的原始代码:
#!/bin/sh
_directory1="~/test1"
_directory2="test2"
for i in $(cd "${_directory1}/$_directory2")
do
echo "$i"
done
波形符 (
~
) 的行为与变量不同。例如,当在引号中使用时,它不会扩展到主目录的路径。在脚本中,使用$HOME
波浪号代替。~
是您可能想在命令行上使用的“快捷方式”,但$HOME
在脚本中更具描述性。- 看 ”为什么波形符 (~) 不在双引号内展开?“ 了解更多信息。
cd
不会输出任何可以循环的内容,因此cd
在命令替换中使用 withfor
不会给您带来任何好处。不幸的是,目前还不清楚您希望循环实际执行什么操作,因此我无法为您提供可靠的替代实现。
包含您编辑的代码:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
这段代码只会输出
"./myscript.sh: 6: cd: can't cd to /test2"
如果变量名称拼写错误_directory1
(并且拼写错误的变量为空,并且/test2
目录不存在)。
然后您编辑了错误消息再次说它输出
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
这仅仅意味着该目录/home/user/test1/test2
不存在。您还没有提供证据证明该目录做存在,所以我们必须相信您的系统的说法。
这是一个列出目录内容的脚本(假设该目录存在)。该代码打印每个文件的完整路径名。
#!/bin/bash
topdir=$HOME/test1
subdir=test2
printf '%s\n' "$topdir/$subdir"/*
或者,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$name"
done
如果给定的模式与任何内容都不匹配, shellnullglob
选项将使循环根本不运行。如果不设置该nullglob
选项,如果 if 不匹配任何内容,则模式将保持未展开状态,并且循环将$name
在单次迭代中使用它作为 for 的值。
如果您对隐藏名称(以字符开头的文件名)感兴趣,您可能还需要设置dotglob
shell 选项 ( )。shopt -s dotglob
.
或者,不打印每个文件名的完整路径,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
printf '%s\n' *
如果失败,将exit 1
终止脚本cd
。
或者,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
shopt -s nullglob
for name in *; do
printf '%s\n' "$name"
done
要仅打印文件名而不打印完整路径,而不使用cd
:
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$( basename "$name" )"
# or: printf '%s\n' "${name##*/}"
done
这将使用该basename
实用程序仅提取路径名的文件名部分。注释中的替代方法是使用标准参数替换,${name##*/}
删除文件名之前的初始目录路径(字面意思是“*/
从中删除与模式匹配的最长前缀字符串$name
”)。