有没有在bash中用波浪号替换主目录的好方法?

Posted

技术标签:

【中文标题】有没有在bash中用波浪号替换主目录的好方法?【英文标题】:Is there a good way to replace home directory with tilde in bash? 【发布时间】:2012-04-19 15:28:28 【问题描述】:

我正在尝试使用路径并用 bash 中的波浪号替换主目录,我希望使用尽可能少的外部程序来完成它。有没有办法只用bash来做到这一点。我得到了

$PWD/#$HOME/\~

但这并不完全正确。它需要转换:

/home/alice to ~
/home/alice/ to ~/
/home/alice/herp to ~/herp
/home/alicederp to /home/alicederp

请注意,以下是 bash 源在转换 \w value in the prompt 时的操作方式:

/* Return a pretty pathname.  If the first part of the pathname is
   the same as $HOME, then replace that with `~'.  */
char *
polite_directory_format (name)
     char *name;

  char *home;
  int l;

  home = get_string_value ("HOME");
  l = home ? strlen (home) : 0;
  if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
    
      strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
      tdir[0] = '~';
      tdir[sizeof(tdir) - 1] = '\0';
      return (tdir);
    
  else
    return (name);

【问题讨论】:

这不是 bash,更像是 C 代码。但是替换几乎没有上下文的字符串很容易出错。你确定要那样做吗? 抱歉,如果不清楚。 C 代码是如何执行此操作的示例。它是 bash 本身如何做到的。 bash 是用 C 编写的程序。现在我想用 bash 语言做同样的事情。 你能告诉我们它现在的输出吗? 好吧,当我说几乎没有上下文的时候,实际上做这样的事情是有很大风险的。 "~" 扩展只在 shell 环境中有效。所以~->主目录扩展是一个shellfeechure,如果你真的尝试从bash以外的地方打开文件,它会失败。例如,C 中的 fopen("~/.bashrc","r") 给出 0,这不是您所期望的。 zsh 用户:在 zsh 中,这只是print -D $PWD 【参考方案1】:

见this unix.stackexchange answer:

如果您使用的是 bash,那么 dirs 内置函数具有所需的 行为:

dirs +0
~/some/random/folder

这可能使用了您粘贴在那里的 Bash 自己的 C 代码。 :)

你可以这样使用它:

dir=...    # <- Use your own here.

# Switch to the given directory; Run "dirs" and save to variable.
# "cd" in a subshell does not affect the parent shell.
dir_with_tilde=$(cd "$dir" && dirs +0)

请注意,这仅适用于已存在的目录名称。

【讨论】:

您可以将dir_with_tilde="$(cd "$dir" &amp;&amp; dirs +0)" 用作单行...但是,如果目录不存在,这将不起作用,因为您无法更改为不存在的目录。您可能正在构建创建路径并希望以友好的方式记录它。 是的,这是我在下面建议的更好方法。感谢dirs 命令的提示:)【参考方案2】:

我不知道作为变量替换的一部分直接执行此操作的方法,但您可以将其作为命令执行:

[[ "$name" =~ ^"$HOME"(/|$) ]] && name="~$name#$HOME"

请注意,这并不完全符合您的要求:它将“/home/alice/”替换为“~/”而不是“~”。这是有意为之,因为有些地方的斜杠很重要(例如,cp -R ~ /backups 的作用与 cp -R ~/ /backups 不同)。

【讨论】:

@Steinar:它应该做你想做的——$name#$HOME 部分采用$name 并从前面删除$HOME(即您的示例中的“/documents”)。有没有可能是你写错字了? @Dennis:Steinar 的解决方案具有与"$PWD/#$HOME/\~" 相同的错误——在 OP 的示例中,它将“/home/alicederp”变成“~derp”。这可以修复,但代价是失去了相当多的可读性。此外,如果您确实使用它,请双引号引用变量引用(即echo "$name")以限制意外解析。 如果您不支持[[ =~ ]] *cough*msys*cough*,您也可以使用tildewd=$(pwd | sed -E "s-^$HOME($|(/.*))-~\2-") 完成它。 该赋值是用 ~ 替换所有出现的 $HOME,还是只替换第一个?在前一种情况下,它应该是固定的。 @MihaiDanila 它只替换字符串开头的$HOME

以上是关于有没有在bash中用波浪号替换主目录的好方法?的主要内容,如果未能解决你的问题,请参考以下文章

Linux bash特性

在 Bash 中用另一个字符替换一个字符

如何在 bash 脚本中用多行/流替换单个流/行?

linux 展开

在日志中用主机名替换 IP

Linux操作系统基础解析之——Bash(Shell)基础知识