bash 从 unix 树中删除路径前缀

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20614157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:00:50  来源:igfitidea点击:

Remove path prefix from unix tree

bashshellunixterminalcommand

提问by Rahul

I have a requirements in UNIX command where i have a path similar to this:

我在 UNIX 命令中有一个要求,我有一个类似于这样的路径:

path/to/file/manyfiles.extensions

now i want the output something similar to-

现在我想要输出类似于-

file/manyfiles.extensions

now i can do this listing both /path/to and /path removing them one by one.

现在我可以列出 /path/to 和 /path 将它们一一删除。

but i might get only "/path/to" as my input and i have to remove both from the tree in one command.

但我可能只得到“/path/to”作为我的输入,我必须在一个命令中从树中删除两者。

You might think that i can list 2 folders to remove, but in many a cases i get structures having 12-13 of subfolders in which i need only the first and last folder in many cases.

您可能认为我可以列出 2 个要删除的文件夹,但在很多情况下,我会得到包含 12-13 个子文件夹的结构,在很多情况下我只需要第一个和最后一个文件夹。

eg - `Source files - target/classes/

例如 - `源文件 - 目标/类/

Remove prefix - target`

删除前缀 - 目标`

Result:

结果:

classes/my/code/HelloWorld.class
classes/my/code/HelloWorldImpl.class
classes/my/code/Main.class

回答by

If I understand your question correctly, you want to strip off some given prefix on a path. Given a declaration path=/a/path/to/a/directoryand a pattern *a/you can strip off the prefix matching that pattern in two ways in Bash:

如果我正确理解您的问题,您想去除路径上的某些给定前缀。给定一个声明path=/a/path/to/a/directory和一个模式,*a/你可以在 Bash 中以两种方式去除匹配该模式的前缀:

echo ${path#*a/}    # outputs "path/to/a/directory"
echo ${path##*a/}   # outputs "directory"

The first variant is non-greedy and stops at the first match, while the second is greedy and stops at the longest possible match for the pattern. The pattern *a/occurs twice in out path here, so the results are then different.

第一个变体是非贪婪的并且在第一次匹配时停止,而第二个是贪婪的并且在模式的最长可能匹配处停止。该模式*a/在此处的输出路径中出现两次,因此结果不同。

In your case the pattern would be something like path/toand the path path/to/file/manyfiles.extensions, so one of the following would work, depending on whether you need to be greedy or not:

在您的情况下,模式将类似于path/topath path/to/file/manyfiles.extensions,因此以下方法之一将起作用,具体取决于您是否需要贪婪:

path=path/to/file/manyfiles.extensions
path=${path#*path/to/}   # assigns "file/manyfiles.extensions" to $path

or

或者

path=path/to/file/manyfiles.extensions
path=${path##*path/to/}  # assigns "file/manyfiles.extensions" to $path

For reference, read about Bash parameter expansion.

作为参考,请阅读有关Bash 参数扩展的信息

回答by Donovan

You'll want to the basenamecommand to strip the directories off your filename, combined with the dirnamecommand which will give you just the directory structure.

您将需要该basename命令从文件名中删除目录,并结合该dirname命令仅提供目录结构。

You can then use whatever logic you require to get the parts of the directory you need to keep, and put it back together with the filename.

然后,您可以使用您需要的任何逻辑来获取您需要保留的目录部分,并将其与文件名一起放回原处。

Something like in this pseudocode:

类似于这个伪代码:

original_file='/some/long/path/to/a/file'
file_name=$(basename $original_file)
dir_name=$(dirname $original_file)

short_dir='...use regex or whatever logic you need to pear ${dir_name} down (we'll need more info to help with this)'

new_file="${short_dir}/${file_name}"

回答by anubhava

You can try grep -oP:

你可以试试grep -oP

p="older2/folder3/folder4/folder5/folder6/folder7/file.txt"
s=$(grep -oP '([^/]+/){2}[^/]+/?$' <<< "$p")
echo "$s"

OUTPUT:

输出:

folder6/folder7/file.txt