如何通过最后一个斜杠分割路径?

105

我有一个文件(假设名为list.txt),其中包含相对路径,每行一个路径,类似于以下内容:

foo/bar/file1
foo/bar/baz/file2
goo/file3

我需要编写一个Bash脚本,逐个处理路径,将其在最后一个斜杠处拆分,然后启动另一个进程并将路径的两个部分作为参数传递给它。到目前为止,我只有循环部分:
for p in `cat list.txt`
do
   # split $p like "foo/bar/file1" into "foo/bar/" as part1 and "file1" as part2
   inner_process.sh $part1 $part2
done

我该如何分割?在路径没有斜杠的情况下,这个方法是否适用?

5个回答

201

只需使用basenamedirname即可。

part1=$(dirname "$p")
part2=$(basename "$p")

1
这个问题的关键在于如何将这些部分组合起来以获取完整路径?$part1/$part2 大多数情况下都可以工作,但如果 $p/etc,你会得到 //etc - Daniel Darabos
1
@DanielDarabos 在大多数情况下,//etc/etc 的有效同义词。但是,如果您需要删除双斜杠,请参阅此问题以获取解决方案:https://dev59.com/7G445IYBdhLWcg3w6eRo - dwymark

19

一种适用于所有文件名,包括空格和特殊符号的100% bash方法(前提是inner_process.sh正确处理它们,但这是另一个故事):

while read -r p; do
    [[ "$p" == */* ]] || p="./$p"
    inner_process.sh "${p%/*}" "${p##*/}"
done < list.txt

这个程序不会为每个文件在子shell中分别执行dirnamebasename命令。

如果$p变量不包含斜杠,则[[ "$p" == */* ]] || p="./$p"代码行会在其前面添加./

有关%##符号的更多信息,请参见Bash参考手册中的Shell参数扩展部分。


18

我从这个来源中找到了一个很好的解决方案。

p=/foo/bar/file1
path=$( echo ${p%/*} )
file=$( echo ${p##*/} )

这也适用于路径中包含空格的情况!


5
翻译英文至中文:${p##*/} - zar3bski
7
子shell和echo也完全不必要,而且当前的解决方案由于未引用扩展而遇到了通常的单词分割问题。不要写这个。只需使用path=${p%/*}file=${p##*/}。或者使用basenamedirname - Konrad Rudolph

1

虽然basename和dirnames非常有用,但也许你和我一样处于同样的情况:

我需要获取路径中仅前N个文件夹,而且我可能在任何一个文件夹中,例如:/home/me/folder/i/want//home/me//home/me/folder/i/want/folder/i/dont/want/

所以我使用了cut

这是获取/home/me/folder/i/want的命令,无论我在哪里:

echo "/home/me/folder/i/want/folder/i/dont/want" | cut -f 1,2,3,4,5,6 -d "/"

这里,cut函数通过"/"字符将字符串分割,并仅显示第1、2、...、6个单词。

以下是一些示例:

$ echo $PWD
/home/me/folder/i/want/folder/i/dont/want
$ echo $PWD | cut -f 1,2,3,4,5,6 -d "/"
/home/me/folder/i/want
$ cd ../../../..
$ echo $PWD
/home/me/folder/i/want
$ echo $PWD | cut -f 1,2,3,4,5,6 -d "/" 
/home/me/folder/i/want
$ cd ~
echo $PWD | cut -f 1,2,3,4,5,6 -d "/"       
/home/me

-2
这里是一个示例,用于查找和替换文件扩展名为xml。
for files in $(ls); do

    filelist=$(echo $files |cut -f 1 -d ".");
    mv $files $filelist.xml;
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接