相当于bash中的cmd“for”?

相当于bash中的cmd“for”?

我对 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 有这个要说的是.:


如果文件名以句点开头.,则应通过使用句点作为模式的第一个字符或紧跟在/斜杠字符后面来显式匹配句点。领先期间不得与以下各项匹配:

  1. *号或?问号特殊字符

  2. 包含非匹配列表的方括号表达式(例如 )、[范围表达式(例如)或字符类表达式(例如][!a]"[%-0]"[[:punct:]]

    • 未指定括号表达式匹配列表中的显式句点(例如 )是否[.abc]可以匹配文件名中的前导句点。

不过,仍然可以循环当前目录中的所有文件 -文件与否 - 在一个循环中就足够了。例如:

set -- .* *
while until [ -f "$1" ] ||
            [ -z "$1" ] &&
            break "$((!$#+1))"
      do    shift;   done
do    printf %s\\n  "$1"
      shift
done

上面打印了当前目录中dashbashkshzshmkshposh和中的所有常规文件yashFOR与典型的 shell 相比,它更类似于 Windows循环for,因为它不会设置任何永久 shell 变量 - 就像cmd FOR它处理其参数一样,当处理完毕后,它们的名称不再具有任何值。在典型的 shell 中,infor中的最后一个值仍然保留。$varfor 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 "*"

也许对你更有用

相关内容