问题是我正在为课堂编写一个脚本,问题是“编写一个脚本,命名实际目录中的所有文件并告诉我们它们的名称和权限”,因此我编写了以下脚本:
#!/bin/bash
for name in `ls -l . | awk {print'$9'}`
do
echo "The file $name has the following permissions: `ls -l . | grep $name | cut -d" " -f1`"
done
好的,脚本在某种程度上可以工作,但问题是它不会显示列表中的所有文件,ls -l
因为我正在打印9th column
(文件的名称),但如果它有一个空格,空格后的单词是column 10
,所以我尝试这样做:
#!/bin/bash
for name in `ls -l . | awk {print'$9,$10'}`
do
echo "The file $name has the following permissions: `ls -l . | grep $name | cut -d" " -f1`"
done
但是当我这样做时,问题是变量 $name 将把第一列和第二列作为单独的单词引用,并且它将显示它们,就好像它们是不同的文件一样。
ls
我也尝试过在使用时转义空格ls -lb
,但是这样grep
命令就不起作用了,如果我使用 grep '$name\s'
它,它会直接复制 $name\s,所以它不会在ls
命令中搜索任何内容...
解决这个问题可能真的很容易,但我已经研究了 5 个多小时却没有任何进展... 任何帮助都非常感谢!
答案1
for name in ./*; do
您还可以使用其他方法改进脚本。
- 在循环中,同样不要解析
ls
。而是使用stat
直接获取权限。1 - 使用较新的命令替换语法,
$(...)
而不是已弃用的反引号`...`
- 定义一个变量
$perms
,使打印字符串更清晰、更易读。
所以:
for name in ./*; do
perms="$(stat -c "%A" "$name")"
echo "The file $name has the following permissions: $perms"
done
脚注:
如果
stat
不存在,并且您必须从获取权限ls
,则可以将文件名作为参数提供给它,并使用该-d
标志,以便它不会进入目录或取消引用符号链接。ls -ld "$name" | cut -d" " -f1
但同样,您不应该解析
ls
。如果任何文件名包含换行符,则此方法会失败。
答案2
写这样的东西绝对不是一个好主意
for stuff in `ls`; ...
ls
解析is的输出一个非常糟糕的主意因为的输出ls
只是文本,并且不能可靠地表示文件的实际名称。
处理文件使用 shell globs反而。
for stuff in *; ...
*
您可以使用而不是./*
,其含义相同,但更安全,因为所有路径都以./
(当前目录)开头,而不是以文件名开头的任何可疑符号开头,后者可能会导致 shell 执行扩展(例如~
)(尽管您绝对应该“引用”您的变量以防止这种不必要的 shell 扩展)或您尝试使用的命令可能会尝试特殊解释的符号(例如-
)。您也可以使用*
而不是,但在循环中运行的命令的所有选项之后./*
添加,以防止以 开头的文件名被解释为选项。这样会给出一个干净的路径,但如果您想使用,有时可以使用 in 命令或其他技巧清理路径。请注意,并非所有命令都支持指示选项的结束。--
-
./*
"$(basename $var)"
--
不要尝试解析您想要的内容ls -l
,而是使用专门用于显示文件元数据的命令并仅询问您想要的输出。
stat -c "%n %A" file
应该能满足您的要求。如果您想显示一条消息,只需将其写入即可:)
以下是我的做法:
for file in *; do stat -c 'The permissions of %n are: %A' -- "$file"; done