我对 bash (或任何 Linux shell - 但我只使用 bash)知之甚少。我习惯for %c in (*.*) do {something}
在Windows中使用cmd,没有它确实感觉很不方便。我尝试了 wine cmd,但它根本无法解释 Linux 命令(我需要 {something}),这不是我想要的。有什么帮助吗?
在 Windows 中,每个文件for %c in (*.*) do {something}
运行{something}
一次(忽略目录)。{something}
可以参考%c
当前迭代的文件名;其他修饰符允许提取文件的路径,或者不带路径的文件名、文件的扩展名、属性、修改日期/时间、大小...for /d %c in (*.*) ...
将处理目录而不是文件。在这两种情况下*.*
相当于*
在 Unix 风格的系统中,它匹配所有非隐藏文件或目录,甚至是那些.
名称中没有的文件或目录。
PS我知道cmd“for”有很多用法,可能无法在bash中的一个命令中涵盖,但我只想知道上面提到的命令的等效项。
答案1
for file in *; do
echo "$file"
done
但这通常与“隐藏”文件(名称以点开头)不匹配。
为了匹配隐藏文件,您之前也需要这样做:
shopt -s dotglob
如果你想跳过目录(可能还有任何“奇怪”的东西),那么你必须在循环中检测它们;模式匹配(*
)不关心对象的类型:
for file in *; do
test -f "$file" || continue
echo "$file"
done
符号链接是一种特殊情况。如果它们链接到文件但该文件可能位于另一个目录中,则将考虑它们。忽略符号链接:
for file in *; do
test -f "$file" || continue
test -L "$file" && continue
echo "$file"
done
答案2
您描述的模式匹配行为是 - 根据此技术网博客- 一个古老的错误:
...您还会发现它本身*.*
是一样的。*
另外...如果您输入DIR .TXT
,命令提示符的行为就像您输入了DIR *.TXT
...这种行为可能...不是故意的,但这是一些人开始依赖的意外。当我们修复 Windows 95 中的错误时,不止一个人抱怨他们的DIR .TXT
命令不起作用。
这巴塞罗那足球俱乐部匹配算法在过渡期间被放弃Win32因为它不适用于长文件名。长文件名可以包含多个点,当然文件的长度可以超过十一个字符,并且点之前可以有八个以上的字符。但有些怪癖巴塞罗那足球俱乐部匹配算法持续到Win32因为它们已经成为习语。
例如,如果您的模式以 结尾.*
,则会.*
忽略 。如果没有此规则,模式将仅匹配包含点的文件,这可能会破坏地球上 90% 的所有批处理文件,以及每个人的肌肉记忆,因为每个运行 Windows NT 3.1 的人都是在一个意味着所有文件的*.*
世界中长大的。*.*
作为另一个示例,以点结尾的模式实际上并不匹配以点结尾的文件;它匹配没有扩展名的文件。如果问号紧接在点之前,则可以匹配零个字符。
这与 Unix 先例的起源可能没有太大不同点文件,如罗布·派克他的博客中的注释:
很久以前,作为设计Unix文件系统正在制定,条目.
和..
出现,以使导航更容易。我不确定,但我相信..
在版本 2 重写过程中,当文件系统变得分层时(它早期的结构非常不同)。然而,当输入 时ls
,这些文件就会出现,因此 Ken 或 Dennis 向程序添加了一个简单的测试。当时是用汇编程序编写的,但有问题的代码相当于这样:
if (name[0] == '.') continue;
该声明比应有的内容短了一点,即
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
...但是嘿,这很容易...
我很确定隐藏文件的概念是一个意想不到的结果。这肯定是一个错误。
(对于那些反对点文件有某种用途的人,我不否认这一点,但反驳说,是这些文件服务了该目的,而不是其名称的约定。它们可以很容易地位于$HOME/cfg
或中$HOME/lib
,这就是我们所做的在计划9,没有点文件。可以吸取教训。)
但从那时起,.
点文件开始与标准 shell.
实用程序相关联,并从那里开始仅与用户特定的纯文本配置文件相关联。
你通常不会发现点文件可以放在除用户之外的任何地方,~
因为这实际上是它们唯一有意义的地方 - 无论如何,用户不应该将任何文件保存在文件系统的其他位置。当处理主目录中的文件时,如果用户意外删除了部分或全部配置文件,那将是不幸的 - 但如果 - 在~
或任何其他目录中 - 循环无意中影响.
-则更不幸 -当前目录 - 或(更糟糕的是) ..
- 父目录。 POSIX 有这个要说的是.
:
如果文件名以句点开头.
,则应通过使用句点作为模式的第一个字符或紧跟在/
斜杠字符后面来显式匹配句点。领先期间不得与以下各项匹配:
星
*
号或?
问号特殊字符包含非匹配列表的方括号表达式(例如 )、
[
范围表达式(例如)或字符类表达式(例如]
[!a]
"[%-0]"
[[:punct:]]
- 未指定括号表达式匹配列表中的显式句点(例如 )是否
[.abc]
可以匹配文件名中的前导句点。
- 未指定括号表达式匹配列表中的显式句点(例如 )是否
不过,仍然可以循环当前目录中的所有文件 -点文件与否 - 在一个循环中就足够了。例如:
set -- .* *
while until [ -f "$1" ] ||
[ -z "$1" ] &&
break "$((!$#+1))"
do shift; done
do printf %s\\n "$1"
shift
done
上面打印了当前目录中dash
、bash
、ksh
、zsh
、mksh
、posh
和中的所有常规文件yash
。FOR
与典型的 shell 相比,它更类似于 Windows循环for
,因为它不会设置任何永久 shell 变量 - 就像cmd
FOR
它处理其参数一样,当处理完毕后,它们的名称不再具有任何值。在典型的 shell 中,infor
中的最后一个值仍然保留。$var
for var in ...
事实并非如此有像那样:
set -- .* * ''
while [ -n "$1" ] || ! shift
do [ -f "$1" ] &&
set -- "$@" "$1"
shift
done
printf %s\\n "$@"
...以可移植的方式实现相同的目标 - 打印当前目录中的所有常规文件 - 但它首先循环一次参数并修剪那些非常规文件。不过,优点是,之后 shell 的 arg"$@"
数组仍然保存整个列表,从那时起您可以执行以下操作:
for f do : something w/ "$f"; done
...在同一阵列上任意多次。但是您还可以获得计数"$#"
并将所有参数连接成单个字符串,"$*"
并且每个参数都可以按排序顺序单独寻址"$1"
..."${10}"
等等。
这些通常不是您可以使用 Win32 执行的操作cmd
。
答案3
如果您对 for 循环学习感兴趣
句法 -
for i in $(command with iterable elements); do command $i; done
喜欢 -
for i in $(echo 1 2 3 4 5); do echo $i; done
如果您对搜索命令感兴趣 -
find . -name "*"
与深度水平 -
find . -maxdepth 1 -name "*"
find . -maxdepth 2 -name "*"
也许对你更有用