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

我有一个文件(例如称为 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

如何分割? 这将工作在退化的情况下,路径没有斜线?

97355 次浏览

Use basename and dirname, that's all you need.

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

A proper 100% bash way and which is safe regarding filenames that have spaces or funny symbols (provided inner_process.sh handles them correctly, but that's another story):

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

and it doesn't fork dirname and basename (in subshells) for each file.

The line [[ "$p" == */* ]] || p="./$p" is here just in case $p doesn't contain any slash, then it prepends ./ to it.

See the Shell Parameter Expansion section in the Bash Reference Manual for more info on the % and ## symbols.

Here is one example to find and replace file extensions to xml.

for files in $(ls); do


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

I found a great solution from this source.

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

This also works with spaces in the path!