从文件路径中删除第一个目录组件

Posted

技术标签:

【中文标题】从文件路径中删除第一个目录组件【英文标题】:Remove first directory components from path of file 【发布时间】:2011-07-15 18:43:03 【问题描述】:

我需要从 Bash 中的变量中删除一个目录(最左侧)。我找到了如何删除所有路径或使用dirname 和其他路径的方法,但它正在删除右侧的所有或一个路径组件;这对我没有帮助。所以你对我需要什么有更好的理解,我会写一个例子:

我有a/project/hello.ca/project/docs/README,...我想删除那个a/,所以在执行一些命令后,我将拥有project/hello.cproject/docs/README,...

【问题讨论】:

【参考方案1】:

您可以使用以下任何一种:

x=a/b/c/d
y=a/
echo $x#a/
echo $x#$y
echo $x#*/

所有三个回显命令都产生b/c/d;当然,您可以以任何您选择的方式使用该值。

当您知道编写脚本时需要删除的名称时,第一个是合适的。

当您有一个包含您需要删除的前缀的变量时,第二个是合适的(次要变体:y=a; echo $x#$y/)。

第三个是最通用的 - 它删除了直到第一个斜杠的任意前缀。当我在 MacOS X 10.6.6 上使用 bash(版本 3.2)测试 * 时,我惊喜地发现它的工作非贪婪 - 我将把它归结为过多的 Perl 和正则表达式工作(因为,仔细想想,shell 中的* 不包括斜线)。

【讨论】:

* 可以在此上下文中包含斜杠。 a='abc/def.ghi'; echo $a#*. 输出“ghi” 但是你是对的,当你使用 # 时它并不贪婪,## 让它变得贪婪。 ### 运算符实际上是做什么的? @Pitt: RTFM?哈希运算符(以“h”开头)从变量的“头”中删除内容。 # 之后的模式与变量的值匹配,匹配的位(如果有)被删除。使用##,将删除最长的匹配项。百分比运算符(尾部带有 't')是 # 的补码,用于从变量尾部删除内容。例如,% 可用于从文件名中删除后缀。 @JonathanLeffler:干杯 :) 又学到了更多关于 bash 的知识! 将它应用到数组时,我惊讶地发现 "$array[@]/#*\/" 是贪婪的,而 "$array[@]/##* \/" 什么都不做。【参考方案2】:
echo a/project/hello.c | cut -d'/' -f2-

【讨论】:

我喜欢这个,简单易概括。我有一个类似的问题,我需要让它工作的只是将 -f2- 中的数字增加到 -f5- 对于我的情况。对其他解决方案中给出的正则表达式做同样的事情会困难得多。【参考方案3】:
echo "a/project/hello.c" | sed 's,^[^/]*/,,'

【讨论】:

【参考方案4】:

man expr

expr "foo/bar/baz" : '[^/]*/\(.*\)' 会做你想做的事。

【讨论】:

【参考方案5】:

您可以通过管道连接到 xargs 并进行新的替换

我如何使用它将 ts-src 下目录中的所有文件从 ts 重命名为 js 和 tsx 重命名为 jsx 到相同的子目录。

find ts-src/ -type f -not -name "*.tsx" -not -name "*.ts" \
  -exec bash -c 'echo "$0##*/" "$0##ts-src/" "$0"'  \; | \
    xargs -l bash -c 'echo mkdir -p "src/$1%$0" && echo cp "$2" "src/$0"'

【讨论】:

【参考方案6】:

上面的例子都没有解决我的问题。我希望能够通过更改 $PATH 值来切换 java 版本。谷歌搜索后找不到足够的答案,我在下面编织了自己的解决方案。

这是我的 .bashrc 中的一段摘录:

jv8() 
    export JAVA_HOME=/opt/jdk1.8.0_121
    y=$(echo $PATH | tr ':' '\n' |sed '/\/opt\/jdk/d' | tr '\n' ':')
    export PATH=$JAVA_HOME/bin:$y


jv6() 
    export JAVA_HOME=/opt/jdk1.6.0_45
    y=$(echo $PATH | tr ':' '\n' |sed '/\/opt\/jdk/d' | tr '\n' ':')
    export PATH=$JAVA_HOME/bin:$y

所以,在我的 bash shell 中,我可以通过以下方式简单地切换:

$> jv6
java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
$> jv8
java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

【讨论】:

以上是关于从文件路径中删除第一个目录组件的主要内容,如果未能解决你的问题,请参考以下文章

Lua从路径中删除第一个目录

目录及文件删除管理

cmd命令

PowerShell - 从字符串路径中删除文件夹

从特定路径中删除文件名?

从二进制文件中删除 protobuf c++ 编译的路径字符串