shell脚本:检查目录名称并转换为小写

时间:2012-10-02 12:18:29

标签: bash shell awk

我希望我的bash脚本检查运行它的目录的名称。类似的东西:

#!/bin/bash

path=eval 'pwd'

dirname=eval 'basename $path'

但它不起作用:我得到了

./foo.sh: line 5: basename $path: command not found

我该如何解决?此外,一旦我得到dirname包含正确的dirname,我就想将其转换为小写,以进行测试。我可以在命令行上使用awk执行此操作:

echo $dirname | awk '{print tolower($0)}'

但是如何将返回值捕获到变量中?提前谢谢你,

最好的问候

塞尔吉奥

7 个答案:

答案 0 :(得分:3)

为什么不使用:

#!/bin/bash

path=`pwd`
dirname=`basename $path | awk '{print tolower($0)}'`

或者如果你想把它作为一个班轮:

dirname=`pwd | xargs basename | awk '{print tolower($0)}'`

答案 1 :(得分:2)

您可以将其重写为

dirname=eval "basename $path"

使用单引号,您不会进行shell扩展,但希望$path扩展。

BTW:我建议使用

path=$(basename $path)

如果您执行类似

的操作,它会更通用,更易读
path=$(basename $(pwd))

或获取小写结果

path=$(basename $(pwd) | awk '{print tolower($0)}')

path=$(basename $(pwd) | tr 'A-Z' 'a-z' )

答案 2 :(得分:2)

表格

x=y cmd

表示暂时将环境变量x设置为值y,然后运行cmd,这就是解释这些行的方式:

path=eval 'pwd'
dirname=eval 'basename $path'

也就是说,它们没有按照您的期望进行操作,而是将环境变量设置为文字值eval,然后运行(或无法找到)命令。正如其他人所说,将命令结果插入字符串的方法是将其放在$(...)(首选)或`...`(遗留)中。并且,作为一般规则,用双引号将它们包装起来更安全(因为在引号中包装任何插值引用更安全)。

path="$(pwd)"
dirname="$(basename "$path")"

(从技术上讲,在这种情况下,外部引号并非绝对必要。但是,我认为它仍然是一个好习惯。)

答案 3 :(得分:0)

B=$(echo "Some text that has CAPITAL letters " | awk '{print tolower($0)}')

答案 4 :(得分:0)

eval执行传递给它的命令,但它只返回命令退出状态代码,因此你无法在set运算符中真正使用它。将命令嵌入到set运算符中以使用正确的单引号或$()

的方法

所以脚本将如下所示:

#!/bin/bash

curr_path=$(pwd)
echo $curr_path
curr_dir=$(basename $curr_path)
echo $curr_dir
echo $curr_dir | awk '{print tolower($0)}'

答案 5 :(得分:0)

您的代码不起作用,因为您使用单引号而不是双引号。单引号可防止变量扩展,因此$path不会扩展到您要使用的路径中,而是按原样使用,因为它是一个字符串。

你的awk调用也不会出于同样的原因。

虽然你可以解决用双引号替换单引号的问题,如下所示:

#!/bin/bash

path=eval "pwd"
dirname=eval "basename $path"

在这种情况下,我建议使用严重的重音(). There's no reason to use eval`。另外,您还可以使用它来收集您感兴趣的返回值:

#!/bin/bash

path=`pwd`
dirname=`basename $path`
variable=`echo $dirname | awk "{print tolower($0)}"`

答案 6 :(得分:0)

这里是我对What platform independent way to find directory of shell executable in shell script?的回答的摘录,除了小写部分之外,它本身完全回答了你的问题,在我看来,这个问题在其他答案中得到了很好的解决。

我的答案的独特之处在于,当我尝试为其他问题编写代码时,我遇到了您确切的问题 - 如何将功能的结果存储在变量? 嗯,正如你所看到的,在一些帮助下,我找到了一个非常简单且非常强大的解决方案:

我可以将函数传递给某种 messenger变量,并取消引用任何明确使用结果函数的$1eval的名称必要时,并且在函数例程完成后,我使用eval和一个反向引用技巧来为我的信使变量分配我想要的值,而不必知道它的名字。

完全披露,虽然这是我的问题的解决方案,我的解决方案 我之前有几次访问过那里,但是他的一些描述虽然可能很精彩,但是我的联盟还有一点,所以我认为如果在前一段中包含我自己的版本,其他人可能会受益。虽然我一旦理解这一点非常简单,特别是对于这一点,我不得不长时间地思考它是如何工作的。无论如何,您可以在Rich's sh tricks找到更多内容,我也在我自己的答案的摘录中摘录了他的页面的相关部分。

... 的摘录: ...

虽然还不是严格的POSIX,realpath 是自2012年以来的GNU核心应用。完全披露:在我info coreutils TOC注意到之前从未听说过它,并立即想到了[链接]问题,但是使用以下函数应该可靠,(很快就是POSIXLY?),我希望,有效率的 为其来电者提供绝对来源的$0

% _abs_0() { 
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath "${1}"`}; eval "$1=\${o1}"; 
> }  
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh

编辑:值得强调的是,此解决方案使用POSIX parameter expansion在尝试执行此操作之前首先检查路径是否实际需要扩展和解析。这应该通过信使变量 返回绝对来源的$0(但值得注意的例外是它会将symlinks保留为有效< / strong>我可以想象它可以完成路径是否已经绝对。 ...

次要编辑 :在文档中找到realpath之前,我至少减少了我的[以下版本]的版本依赖于时间字段[就像它在第一个ps命令中所做的那样],但是,公平警告,在测试之后我不太相信ps在其命令路径扩展能力方面是完全可靠的

另一方面,你可以这样做:

ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"

eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"

... 来自Rich's sh tricks ...

从shell函数返回字符串

从上面的命令替换缺陷中可以看出,stdout不是shell函数将字符串返回给调用者的好途径,除非输出采用尾随换行无关紧要的格式。当然,这种做法对于处理任意字符串的函数是不可接受的。那么,可以做些什么呢?

试试这个:

func () {
body here
eval "$1=\${foo}"
}

当然${foo}可以替换为任何类型的替换。这里的关键技巧是评估线和转义的使用。当eval的参数由主命令解析器构造时,“$1”被扩展。但是“${foo}”在此阶段尚未展开,因为“$”已被引用。相反,当eval评估其参数时,它会被扩展。如果不清楚为什么这很重要,请考虑以下情况如何:

foo='hello ; rm -rf /'
dest=bar
eval "$dest=$foo"

但当然以下版本是绝对安全的:

foo='hello ; rm -rf /'
dest=bar
eval "$dest=\$foo"

请注意,在原始示例中,“$1”用于允许调用者将目标变量名称作为函数的参数传递。如果您的函数需要使用shift命令,例如将剩余的参数作为“$@”处理,那么将“$1”的值保存在函数开头的临时变量中可能很有用。