嗨......这里需要一点帮助......
我尝试使用bash脚本在Linux中模拟DOS'dir
命令。基本上它只是一个包含ls
命令,带有一些参数和摘要信息。这是脚本:
#!/bin/bash
# default to current folder
if [ -z "$1" ]; then var=.;
else var="$1"; fi
# check file existence
if [ -a "$var" ]; then
# list contents with color, folder first
CMD="ls -lgG $var --color --group-directories-first"; $CMD;
# sum all files size
size=$(ls -lgGp "$var" | grep -v / | awk '{ sum += $3 }; END { print sum }')
if [ "$size" == "" ]; then size="0"; fi
# create summary
if [ -d "$var" ]; then
folder=$(find $var/* -maxdepth 0 -type d | wc -l)
file=$(find $var/* -maxdepth 0 -type f | wc -l)
echo "Found: $folder folders "
echo " $file files $size bytes"
fi
# error message
else
echo "dir: Error \"$var\": No such file or directory"
fi
问题是当参数包含星号(*)时,脚本中的ls
与提示时给出的直接ls
命令的行为不同。该脚本仅返回第一个文件,而不是返回整个文件列表。请参阅下面的视频,了解实际比较情况。我不知道为什么会这样。
任何人都知道如何修复它?谢谢。
更新:
问题已经解决了。谢谢大家的答案。现在我的脚本按预期工作了。观看视频:http://i.giphy.com/3o8dp1YLz4fIyCbOAU.gif
答案 0 :(得分:5)
在解析命令行时,shell会扩展星号*
。换句话说,您的脚本没有获得包含星号的参数,它获取文件列表作为参数。您的脚本仅适用于第一个参数$1
。它应该与"$@"
匹配。
答案 1 :(得分:4)
这是因为当您检索$1
时,您认为shell不会展开*
。
事实上,当*
(或其他全局)匹配时,它会被展开,并按$IFS
分成若干段,然后传递为$1
,$2
,等
如果您只是检索了第一个文件,那么您很幸运。当您的第一个文件的路径包含空格时,您将收到错误,因为您只获得该空格之前的第一个段。
请不要做
之类的事情CMD=whatever you get from user input; $CMD;
你正在乞求麻烦。不要从用户那里执行任意字符串。
答案 2 :(得分:1)
以上两个答案都已经回答了你的问题。所以,我会更加冗长。
在您的终端中运行bash
解释器(可能)。这是一个程序,它根据您的输入解析您的输入行和做“事情”。
当您输入某行时,bash
开始执行以下工作流程:
仅在bash
ls
或dir.sh
...等等,builtins
,echo
,for
等等{...}} 如您所见,最后一个是文件名生成(通配)。因此,在您的情况下 - 如果if
与某些文件匹配,那么您的test*
会扩展 willcard字符(也就是通配符)。
所以,
bash
时,dir.sh test*
匹配某些文件test*
dir.sh
顺便说一句,它完全符合dir.sh test.pas test.swift
示例的相同方式:
ls
将bash
扩展为ls test*
ls test.pas test.swift
ls
将打印获得两个参数的结果。ls
甚至看不到ls
参数 - 如果可能的话 - test*
扩展wilcard字符。 (bash
和*
)。现在回到你的脚本:在shebang之后添加以下行:
?
你会立刻看到,真正的争论是你的剧本如何被执行。
同样,在这种情况下尝试以调试模式执行脚本是一种很好的做法,例如
echo "the $0 got this arguments: $@"
你会看到,剧本的确切行为。
此外,您可以为当前的口译员执行相同操作,例如:进入终端
bash -x dir.sh test*
并尝试运行set -x
=,您将看到dir.sh test*
将如何执行bash
命令。 (要停止调试模式,只需输入dir.sh
)
答案 3 :(得分:0)
Everbody正在为您提供宝贵的建议,您应该遵循这些建议!
但这是你问题的真实答案。
要将未展开的参数传递给任何可执行文件,您需要单引号:
./your_script '*'
答案 4 :(得分:0)
我最好的解决方案是通过以下方式使用eval命令:
#!/bin/bash
cmd="some command \"with_quetes_and_asterisk_in_it*\""
echo "$cmd"
eval $cmd
eval命令采用其参数,并像shell一样将其求值到命令中。 当我需要从脚本中调用带有星号“ *”的命令时,这解决了我的问题。