【问题标题】:An alias in .bashrc fails vs command line succeeds.bashrc 中的别名失败 vs 命令行成功
【发布时间】:2018-07-21 21:14:19
【问题描述】:

我从用户的主目录运行它以显示最新的文件,同时省略 shell 配置文件:

find ./ -type f -printf "%T@ %p\n"|grep -vP "/\.(bash|emacs|gtkrc|kde/|zshrc)" |sort -n| tail -10|cut -f2- -d" "|while read EACH; do ls -l "$EACH"; done;

这可行,但在我的 .bashrc 作为别名放置时效果不佳:

alias recentfiles='find ./ -type f -printf "%T@ %p\n"|grep -vP "/\.\(bash|emacs|gtkrc|kde/|zshrc\)"|sort -n| tail -10|cut -f2- -d" "|while read EACH; do ls -l "$EACH"; done;'

在图像中,您会看到未进行任何过滤的结果,然后是使用grep -v 进行过滤的所需结果,该过滤可在命令行上运行。然后最终结果 - 仅部分成功地清除了这些文件。

我尝试过使用 bash_ 和 [b]ash。甚至 bas (甚至无法获得 .basin)都无法工作?!?而且我也可以使用macs或acs并且仍然省略.emacs,所以很明显我的别名中的语法不尊重/。任何一个。保留字不是我原先想的问题。

如果我将原始命令按原样放在文件中,然后以这种方式使用别名,我 DO 会得到预期的结果: 别名最近文件='。 /root/mycommands/recentfiles'

有人可以解释或指出一个参考来了解这里的作用吗?我不知道要搜索什么词组。

【问题讨论】:

  • 你为什么不告诉find 过滤掉那些?
  • 使用函数代替 ;)
  • 创建别名意味着 shell 会扫描该命令行并在单个和 dbl 引用的字符串上执行魔术。在通过处理激活它之后,很难理解 cmd 字符串处于什么“状态”(哪些引号和转义字符已被消耗,哪些仍然存在)。尝试修复别名真的不值得你花时间,更好地使用函数,它们是可调试的,它们可以接受运行时参数,而且你不必欺骗 shell 解析器来让它们工作。恕我直言,祝你好运。
  • find 命令中使用! \( -name .bash -o -name .emacs -o ... \) 而不是grep
  • 当您写“在图片中,您看到”时,我假设您尝试发布图片,但不知何故无法发布。没关系,反正直接复制粘贴终端输出会好很多。

标签: bash shell alias


【解决方案1】:

这应该可以解决您的问题:

alias recentfiles='find ./ -type f -printf "%T@ %p\n"|grep -vP "/\.(bash|emacs|gtkrc|kde/|zshrc)"|sort -n| tail -10|cut -f2- -d" "|while read EACH; do ls -l "$EACH"; done;'

问题在于grep -P,其中 -P 使它使用 perl 正则表达式。在 perl 中,不需要在分组中使用 \。所以 (bash|emacs|...) 而不是 \(bash|emacs|...\) 。我真的怀疑它在 .bashrc 之外是否有效,除非您有一些 grep 的别名,这使它在 .bashrc 之外的行为有所不同。

正如其他人在 cmets 中所说,您的过滤效率低下。更好地重写你的命令:

find ./ \( -name ".bash*" -o -name ".emacs*" -o -name .gtkrc -o -name .kde -o -name .zshrc \) -prune -o \( -type f -printf "%T@ %p\n" \) |sort -n| tail -10|cut -f2- -d" "| tr "\n" "\0" | xargs -0 ls -l;

这样它就不会浪费时间在.emacs.d/.kde/ 内搜索文件,并且会立即修剪搜索。此外,xargs -0 ls -l 比 while 循环更短更清晰。

为避免包含换行符的文件名出现问题,最好使用 \0 字符,它们绝不是文件名的一部分:

find ./ \( -name ".bash*" -o -name .emacs -o -name .gtkrc -o -name .kde -o -name .zshrc \) -prune -o \( -type f -printf "%T@ %p\0" \) |sort -n -z | tail -z -n -10| cut -z -f2- -d" " | xargs -0 ls -l

【讨论】:

  • xargs ls -l 将与带有空格的文件名出现错误:如果您有一个名为 foo bar 的文件,您将运行 ls -l "foo" "bar"。至少,使用xargs -d $'\n' ls -l 来正确处理带有空格或引号的文件名;最好重写管道的其余部分以使用 NUL 分隔符来正确处理带有文字换行符的文件名。
  • 是的,正确的。但是整个 printf "%T@ %p\n" 都遇到了类似的问题。它不适用于换行符。我将用 \0 替换 \n,用 xargs -0 替换 xargs,
  • 修复了文件名中带有 \n 的问题,使用 \0 作为行终止符
【解决方案2】:

第 1 部分:解决问题

改用函数。

别名有几个主要问题:

  • 因为您在创建别名时将内容以字符串作为前缀传递到引号内,所以它的解析方式与直接在命令行键入时不同。

  • 因为别名是简单的前缀替换,它们没有自己的参数($1$2 等);他们没有调用堆栈; PS4=':$BASH_SOURCE:$LINENO+'; set -x 之类的调试机制无法告诉您来自别名的哪个文件代码;等等

  • 别名是一种交互功能; POSIX 根本不要求 shell 支持它们,并且它们在脚本执行期间默认关闭。

函数解决了所有这些问题。

recentfiles() {
  find ./ \
      '(' -name '.bash*' -o -name '.emacs*' -o -name .gtkrc -o -name .kde -o -name .zshrc ')' -prune \
      -o -type f -printf "%T@ %p\0" |
    sort -nz |
    tail -z -n -10 |
    while read -d' ' _ && IFS= read -r -d '' file; do
      printf '%s\0' "$file"
    done |
    xargs -0 ls -ld --
}

请注意,我还进行了其他一些更改:

  • 上面的代码没有使用\n作为分隔符,而是使用\0。这是因为可以在文件名中找到换行符;对于管道的其余部分,名称中包含换行符的文件可能看起来像任意数量的文件,具有它想要的任意大小。 (不幸的是,POSIX 不要求 sorttail 支持换行符,因此上面使用的 -z 选项是 GNUisms)。
  • 我没有使用grep -v 来删除点文件,而是使用-prune 选项到find。这对于像 .kde 这样的目录尤其重要,因为它会阻止 find 花费时间和 I/O 带宽来递归您打算丢弃结果的目录。
  • 有关while read 循环中使用的IFS=-r 参数的重要性的文档,请参阅BashFAQ #1。这两种方法都可以改善存在异常文件名时的行为(清除 IFS 可防止尾随空格被剥离;传递 -r 可防止文字反斜杠被省略)。
  • 而不是 grep -P——一个 GNU 扩展,只有在 grep 编译时支持 libpcre 时才可用——我的第一个剪辑(在移动到 find -prune 之前)切换到 grep -E,它具有足够的表现力,更广泛可用,以及lends itself to higher performance implementations

第 2 部分:解释问题

set -x 之后运行你的别名,我们看到:

+ find ./ -type f -printf '%T@ %p\n'
+ grep -vP '/\.\(bash|emacs|gtkrc|kde/|zshrc\)'
+ sort -n
+ tail -10
+ cut -f2- '-d '
+ read EACH

相比之下,运行它打算包装的命令,我们看到:

+ find ./ -type f -printf '%T@ %p\n'
+ grep -vP '/\.(bash|emacs|gtkrc|kde/|zshrc)'
+ sort -n
+ tail -10
+ cut -f2- '-d '
+ read EACH

在命令本身中,() 之前没有文字反斜杠。

【讨论】:

    猜你喜欢
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    相关资源
    最近更新 更多