79

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

我该如何拆分?这在路径没有斜杠的退化情况下是否有效?

4

4 回答 4

162

使用basenameand dirname,这就是你所需要的。

part1=$(dirname "$p")
part2=$(basename "$p")
于 2012-12-07T16:43:33.620 回答
18

一种正确的 100% bash 方式,并且对于包含空格或有趣符号的文件名是安全的(前提inner_process.sh是正确处理它们,但这是另一回事):

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

并且它不会为每个文件分叉dirname和(在子shell中)。basename

该行[[ "$p" == */* ]] || p="./$p"位于此处以防万一$p不包含任何斜线,然后将./其放在前面。

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

于 2012-12-07T19:11:58.377 回答
9

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

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

这也适用于路径中的空格!

于 2018-06-21T19:53:45.250 回答
-2

这是一个查找和替换 xml 文件扩展名的示例。

for files in $(ls); do

    filelist=$(echo $files |cut -f 1 -d ".");
    mv $files $filelist.xml;
done
于 2014-08-13T06:04:16.870 回答