在bashrc中使用别名时,如何测试可能的冲​​突?


12

有没有一种简单的方法来列出由于涉及别名命令的bashrc更新而导致系统中发生的所有命令冲突?

例如,有人alias ls=/path/to/user-generated/executable用bashrc 编写。如何发现这掩盖了实际命令(ls)。一种方法似乎是在采购bashrc之前和之后运行所有别名并比较输出。有没有更好的方法?

我正在运行Ubuntu 12.04。

bash --version

GNU bash版本4.2.24(1)-发行版(i686-pc-linux-gnu)


附带说明,如果您提供bash版本而不是操作系统版本,则在回答特定于bash的问题时,这通常对人们回答更为有用。
jordanm 2012年

@jordanm更新。
user13107 2012年

Answers:


8

要找出别名掩盖了哪些命令,请执行以下操作:

alias | sed 's/^[^ ]* *\|=.*$//g' | while read a; do
  printf "%20.20s : %s\n" $a "$(type -ta $a | tr '\n' ' ')"
done | awk -F: '$2 ~ /file/'

说明

alias仅列出定义的别名并sed提取其名称。while循环type -ta在每个循环上运行,并awk打印包含别名和文件的行。


15

您可以使用它type来查找bash如何解释命令。


例如,在这里type ls打印ls is aliased to `ls --color=auto'
l0b0 2012年

Same确实适用于which,但是如果两个(类型,哪个)shell内建函数相同,我现在就不这样做。
数学

@math:type which告诉您which is /usr/bin/which,所以它不是内置函数。因此,它不能告诉您某些东西是否是内置的(例如which echovs type echo)。
choroba

我猜这取决于您使用的shell:type which which is a shell builtin我正在使用zsh。
数学

@math:原始问题被标记为/ bash。
choroba

7

作为第一个问题,无法列出冲突,因为bash在内部使用哈希表,因此它仅记录最后一个替代。

要确定命令是否为别名,请alias ls在您的情况下使用,如果命令告诉您“未找到”之类的信息,则它不是别名,否则为别名。

要启动不考虑别名的原始功能,请在斜杠前面加上一个斜杠(例如,\ls将启动真实的哈希ls),请忽略别名。

编辑

如果您想快速知道命令是否为别名,则可以通过set -x执行ls以下命令启用调试模式:

在此处输入图片说明

您将看到正在执行的真实命令的调试输出

要取消设置调试模式,请使用 set -


谢谢。但没有得到alias一部分。如果用户不知道存在命令(例如ls)怎么办?运行后,他似乎只知道alias ls映射的内容,而不是原始映射的内容。我猜一个人将不得不使用和不使用\来运行所有命令来查找冲突。
user13107 2012年

@ user13107更新了答案
雏菊

谢谢。如何取消追踪?
user13107 2012年

@ user13107再次更新;-P
雏菊

1
“没有办法列出冲突” –您只是缺乏想象力。
camh 2012年

6

您可以使用内置的bash compgen来获取所有命令和所有别名的列表compgen -ac。任何也是别名的命令都将在此列表中重复,因此简单的天真解决方案是在中输出查找重复项compgen -ac

但是,如果命令在路径上两次出现,则可能还会出现重复项。举例来说,我有/bin/which/usr/bin/which这样compgen -ac会列出which两次,即使它不是一个别名。

因此,需要从中获取所有重复项compgen -ac并将其与别名列表进行比较。只有也是别名的重复项才是那些隐藏命令的别名。我们可以使用comm(1)命令和bash进程替换来做到这一点。

comm -12 <(compgen -a | sort) <(compgen -ac | sort | uniq -d) 

compgen -a | sort是所有别名的列表(按排序comm)。compgen -ac | sort | uniq -d是命令和别名列表中所有重复项的列表。comm -12仅输出两个共同的行。


5

您可以使用shell调试功能来确切了解bash调用交互式shell时发生的情况。下面应该显示从登录shell生成交互式shell时分配的所有别名:

bash -x -l -i -c 'exit' 2>&1 | grep ' alias '
  • -x ->启用调试
  • -l ->登录外壳
  • -i ->交互式外壳
  • -c ->命令

需要运行命令出口,以便外壳程序返回。该-i在这种情况下,因为需要的bash不会建立一个互动的环境,否则运行命令。

这是我系统中的一个示例:

$ bash -x -l -i -c 'exit' 2>&1 | grep ' alias '
++ alias 'ls=ls --color=auto'
$ alias -p
alias ls='ls --color=auto'

为了查看在分配别名以确定文件出现时最后一个来源的文件,可以扩展grep:

bash -x -l -i -c 'exit' 2>&1 | grep -E ' (alias|[.]|source) '

这可能会返回误报,但如果您正在手动检查返回的数据,那应该没问题。执行命令前面的“ +”号表示深度。

+ . /home/jordan/.bashrc
++ alias 'ls=ls --color=auto'
++ . /home/jordan/.foo
+++ alias t=test
++ alias t=test2

在此示例输出中,它显示了.bashrc为ls.foo别名设置了别名t,然后.bashrc覆盖了t。的先前别名。


谢谢。这当然是有用的,但看不到如何找到创建别名的冲突。
user13107 2012年

@ user13107我添加了更多详细信息,应该会有所帮助。将别名设置为新值不是“冲突”别名。这是正常的行为记录,这就是为什么需要一种绕行方式的原因。
jordanm 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.