最近我制作了一个权限为 722 的 bash 可执行文件,因为我几乎永远是 root。文件内容如下:
#!/home/nolan/Documents/test/listFiles
[ $# -lt 1 ] && dirFocus = "" || dirFocus = $1
dirSize=$(ls -a $dirFocus | wc -w)
for ((a = 1; a <= $dirSize; a++)) ; do
i = 1
for ITEM in $(ls -a $dirFocus); do
declare -i i
declare -i a
if [ $a -eq $i ]; then
echo "$a : $ITEM"
fi
i = $[ $i + 1 ]
done
done
在终端中运行时使用:
root @ /home/nolan/Documents/test: bash listFiles
1 : .
2 : ..
3 : apple
4 : dirCheck
5 : ifTest
6 : ifTest.txt
7 : listFiles
8 : myscript
9 : nolan.txt
10 : pointer_to_apple
11 : scriptx.sh
12 : Stuff
13 : weekend
14 : weekend2
15 : weekend3
我如预期收到了这个结果。然而第二个我这样做:
root @ /home/nolan/Documents/test: ./listFiles
bash: ./listFiles: /home/nolan/Documents/test/listFiles: bad interpreter: Too
many levels of symbolic links
是我得到的错误。究竟出了什么问题?我检查过其他论坛,但它们似乎不适合我的情况。
答案1
脚本的第一行是“shebang”行。它告诉内核(程序加载器)运行哪个程序来解释脚本。您的脚本尝试运行自身来解释脚本,脚本又调用自身来解释解释器,依此类推。
当您使用 运行脚本时bash filename
,不会调用内核,而是使用 bash 来运行有效的脚本。
放
#! /bin/bash
到第一行,一切都会好起来的。
顺便说一句,创建一个具有有限权限的用户来试验系统。因为root
,你可以轻易地摧毁一切无法修复的东西。
答案2
choroba解释得很好您的问题是 shell 脚本使用自身作为解释器而不是bash
.
这是重新实现脚本的建议
不包含语法错误(
dirFocus = ""
例如,=
赋值中不应有空格的语法错误)。处理包含空格和换行符的文件名(循环遍历输出
ls
会取消任何此类文件名的资格,wc -w
如果任何文件名包含空格,同样会得到错误的计数)。使用现代 shell 语法(
$[ $i + 1 ]
已过时的bash
语法)。介绍微小的输出的改进(添加
(dir)
到目录名称)。
#!/bin/bash
shopt -s dotglob # make wildcards match hidden names by default
shopt -s nullglob # make wildcards expand to nothing if no match
count=0
for name in "${1:-.}"/*; do
count=$(( count + 1 ))
if [ -d "$name" ]; then
printf '%d : %s (dir)\n' "$count" "${name##*/}"
else
printf '%d : %s\n' "$count" "${name##*/}"
fi
done
这也不会多次扩展文件列表,而您的代码会对ls
目录中的每个名称执行整个目录的操作。
${1:-.}
意思是“使用其中的内容,$1
除非它是空的或未设置的,否则使用.
”。
${name##*/}
表示“ 中的字符串$name
,但没有到最后一位/
”。