39

我正在尝试编写一个 bash 脚本,允许用户使用通配符传递目录路径。

例如,

bash show_files.sh *

在此目录中执行时

drw-r--r--  2 root root  4.0K Sep 18 11:33 dir_a
-rw-r--r--  1 root root   223 Sep 18 11:33 file_b.txt
-rw-rw-r--  1 root root   106 Oct 18 15:48 file_c.sql

会输出:

dir_a
file_b.txt
file_c.sql

现在的方式,它输出:

dir_a

内容show_files.sh

#!/bin/bash

dirs="$1"

for dir in $dirs
do
    echo $dir
done
4

2 回答 2

58

调用 的父 shell会为您bash show_files.sh *扩展*

在您的脚本中,您需要使用:

for dir in "$@"
do
    echo "$dir"
done

双引号确保正确处理文件名中的多个空格等。

另请参阅如何迭代bashshell 脚本中的参数。


可能令人困惑的附录

如果您确实确定要让脚本扩展*,则必须确保将*其传递给脚本(如其他答案一样,用引号括起来),然后确保它在正确的点展开在处理中(这不是微不足道的)。那时,我会使用一个数组。

names=( $@ )
for file in "${names[@]}"
do
    echo "$file"
done

我不经常使用$@双引号,但这是一次或多或少正确的做法。棘手的部分是它不能很好地处理带有空格的通配符。

考虑:

$ > "double  space.c"
$ > "double  space.h"
$ echo double\ \ space.?
double  space.c double  space.h
$

这很好用。但是尝试将它作为通配符传递给脚本并且......好吧,我们只是说它在那时变得很棘手。

如果要$2单独提取,则可以使用:

names=( $1 )
for file in "${names[@]}"
do
    echo "$file"
done
# ... use $2 ...
于 2013-10-18T20:07:00.330 回答
11

引用通配符:

bash show_files.sh '*'

或者让你的脚本接受一个参数列表,而不仅仅是一个:

for dir in "$@"
do
    echo "$dir"
done

最好直接迭代"$@'而不是将其分配给另一个变量,以保留其保存本身包含空格的元素的特殊能力。

于 2013-10-18T20:07:15.970 回答