为什么我不能将目录作为参数传递给 bash 中的 for 循环?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15763044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:04:05  来源:igfitidea点击:

Why can't I pass a directory as an argument to a for loop in bash?

bashdirectory

提问by SamIAm

I have a simple bash script, simple.sh, as follows:

我有一个简单的 bash 脚本 simple.sh,如下:

#/usr/local/bin/bash
for i in 
   do
       echo The current file is $i
   done

When I run it with the following argument:

当我使用以下参数运行它时:

./simple.sh /home/test/*

it would only print and list out the first file located in the directory.

它只会打印并列出目录中的第一个文件。

However, if I change my simple.sh to:

但是,如果我将 simple.sh 更改为:

#/usr/local/bin/bash
DIR=/home/test/*
for i in $DIR
   do
       echo The current file is $i
   done

it would correctly print out the files within the directory. Can someone help explain why the argument being passed is not showing the same result?

它会正确打印出目录中的文件。有人可以帮助解释为什么传递的参数没有显示相同的结果吗?

采纳答案by Oni1

If you take "$1", it is the first file/directory, which is possible! You should do it in this way:

如果你取“$1”,它是第一个文件/目录,这是可能的!你应该这样做:

for i in "$@"
do
  echo The current file is ${i}
done

If you execute it with:

如果你执行它:

./simple.sh *

They list you all files of the actual dictionary

他们列出了实际字典的所有文件

"$1" is alphabetical the first file/directory of your current directory, and in the for loop, the value of "i" would be e.g. a1.sh and then they would go out of the for loop! If you do:

“$1”按字母顺序表示当前目录的第一个文件/目录,在for循环中,“i”的值将是例如a1.sh,然后它们将退出for循环!如果你这样做:

DIR=/home/<s.th.>/* 

you save the value of all files/directories in DIR!

您将所有文件/目录的值保存在 DIR 中!

回答by Jens

This is as portable as it gets, has no useless forks to ls and runs with a minimum of CPU cycles wasted:

这是尽可能可移植的,没有无用的 ls 分支,并且运行时浪费了最少的 CPU 周期:

#!/bin/sh
cd 
for i in *; do
   echo The current file is "$i"
done

Run as ./simple.sh /home/test

运行方式 ./simple.sh /home/test

回答by chepner

Your script does not receive "/home/test/*" as an argument; the shell expands the patter to the list of files that match, and your shell receives multiple arguments, one per matching file. Quoting the argument will work:

您的脚本没有接收“/home/test/*”作为参数;shell 将模式扩展为匹配的文件列表,并且您的 shell 接收多个参数,每个匹配文件一个。引用论点将起作用:

./simple.sh "/home/test/*"

Your change to using DIR=/home/test/*did what you expected because filename generation is not performed on the RHS of a variable assignment. When you left $DIRunquoted in the forloop, the pattern was expanded to the list of matching files.

您对 using 的更改DIR=/home/test/*符合您的预期,因为文件名生成不是在变量赋值的 RHS 上执行的。当您$DIRfor循环中不加引号时,模式将扩展为匹配文件的列表。

回答by Jintian DENG

How about list the file manully instead of using *:

如何手动列出文件而不是使用 *:

  #/usr/local/bin/bash
  for i in $(ls )
  do
      echo The current file is $i
  done

and type

并输入

 ./simple.sh /home/test/