一个似乎不起作用的bash函数定义

3
我最近在尝试使用shell函数,目的是覆盖ls命令。我的意图是让shell首先调用我的ls函数,然后如果第一个开关是“-y”,则执行一些操作,否则调用常规的/bin/ls。但结果表现出我不理解的行为。
为了启用它,我决定使用“-y”作为开关,因为:
$ ls -y
ls: invalid option -- 'y'
Try `ls --help' for more information.

因此,它不能破坏ls的核心功能。无论如何,将问题简化,并且使用其他几个示例来帮助突出问题:

$ function ls() { [[ "y$1" == "y-y" ]] && echo LS ; } 
$ function less() { [[ "y$1" == "y-y" ]] && echo LESS ; }
$ function try() { [[ "y$1" == "y-y" ]] && echo TRY ; }

所以我正在覆盖lsless并定义try,它类似于“控制”标本 :)

现在这样调用:

$ ls ; less ; try 

它的表现如预期一样(没有输出),但是:
$ ls -y ; less -y ; try -y
LESS
TRY

ls命令无法正常工作,但less覆盖命令和"control"命令可以正常工作。

在stackoverflow或askubuntu的其他地方(但我暂时找不到参考资料)中,我看到了一个示例,暗示ls是内置命令,但实际上:

$ which ls
/bin/ls

并且:

$ builtin ls
bash: builtin: ls: not a shell builtin

所以在我的系统上似乎没有这个问题(即使有也不清楚为什么会出现这种情况)。

我想知道这是什么原因?虽然这不重要,但我想了解发生了什么。

谢谢。


阅读了答案后,我决定添加这个评论:“哎呀!” - Thorsen
你的意思是你不记得那半打命令的区别,你输入的命令并不是实际执行的命令吗?新手!;) - msw
“当你叫我那个名字时,请微笑。” :) - Thorsen
1
我认为发生的事情是,我过于专注于“内置”这件事,而排除了任何其他解释,即使它实际上无法解释任何问题。“当问题不在你寻找的地方时,它就在别的地方!”重复100遍。 - Thorsen
3个回答

6
不要使用which,使用type。如果你有类似以下的东西:
$ type ls
ls is aliased to `ls --color=auto'

如果你在交互式shell中运行函数,它将失败。请在.bashrc或定义函数的任何位置中删除此内容。您还可以使用unalias内置命令。

如果在函数内运行与函数同名的命令,请避免递归。

ls()
    if [[ $1 == -y ]]; then
        shift
        ...
    else
        command ls "$@"
    fi

另外,如果你决定使用 function 关键字定义函数,确保你知道自己在做什么。在需要 POSIX 兼容性时,请使用 POSIX 风格的 funcname() compound-command,根据本文所述。


1
@msw type非常好用。我可以说在面向Bash编程时,它是首选。不幸的是,POSIX对于它实际应该做什么几乎没有提及,所以选项和确切的输出会有很大差异。 - ormaaj
感谢ormaaj。我的“真实”版本有一个递归检查:这只是简化到最简单情况的过程。 - Thorsen

5

通常会为ls设置别名,这可能是您的情况。别名首先被处理,这是文本的简单替换。在您的示例中发生的是:

A) `ls` is replaced with `ls --color=auto` 
B) Your `ls` function is called with the replaced text and your -y option 
C) Your function checks "$1", which is --color=auto

以下是此行为的示例:
$ function ls() { [[ "y$1" == "y-y" ]] && echo LS ; }
$ ls -y
$ type ls
ls is aliased to `ls --color=auto'
$ unalias ls
$ type ls
ls is a function
ls ()
{
    [[ "y$1" == "y-y" ]] && echo LS
}
$ function ls() { [[ "y$1" == "y-y" ]] && echo LS ; }
$ ls -y
LS
$ alias ls="ls --color=auto"
$ ls -y
--color=auto -y

1

我猜想

$ alias ls

会向您展示原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接