如何提取直接目录的名称和文件名?

时间:2010-02-26 07:21:37

标签: unix sed awk

我有一个完整路径就像

的文件
/a/b/c/d/filename.txt

如果我对其进行了basename,我会得到filename.txt。但是这个文件名并不是太独特。

因此,如果我可以将文件名提取为d_filename.txt,即

,那会更好
{immediate directory}_{basename result}

如何实现此结果?

5 个答案:

答案 0 :(得分:2)

file="/path/to/filename"
echo $(basename $(dirname "$file")_$(basename "$file"))

file="/path/to/filename"
filename="${file##*/}"
dirname="${file%/*}"
dirname="${dirname##*/}"
filename="${dirname}_${filename}"

答案 1 :(得分:1)

这段代码将以你运行脚本的目录开始递归搜索你的层次结构。我已经用这样的方式对循环进行编码,它将处理你抛出的任何文件名;带空格,换行符等的文件名。

*注意**:循环当前写入 包含此脚本所在目录中的所有文件,它只查看它下面的子目录。这样做是因为它是确保脚本在处理过程中不包含自身的最简单方法。如果由于某种原因您必须包含脚本所在的目录,则可以更改它以适应此目的。

代码

#!/bin/bash

while IFS= read -r -d $'\0' file; do
    dirpath="${file%/*}"
    filename="${file##*/}"
    temp="${dirpath}_${filename}"
    parent_file="${temp##*/}"

    printf "dir: %10s  orig: %10s  new: %10s\n" "$dirpath" "$filename" "$parent_file"
done < <(find . -mindepth 2 -type f -print0)

测试树

$ tree -a
.
|-- a
|   |-- b
|   |   |-- bar
|   |   `-- c
|   |       |-- baz
|   |       `-- d
|   |           `-- blah
|   `-- foo
`-- parent_file.sh

输出

$ ./parent_file.sh
dir:  ./a/b/c/d  orig:       blah  new:     d_blah
dir:    ./a/b/c  orig:        baz  new:      c_baz
dir:      ./a/b  orig:        bar  new:      b_bar
dir:        ./a  orig:        foo  new:      a_foo

答案 2 :(得分:0)

$ FILE=/a/b/c/d/f.txt
$ echo $FILE
/a/b/c/d/f.txt
$ echo $(basename ${FILE%%$(basename $FILE)})_$(basename $FILE)
d_f.txt

答案 3 :(得分:0)

不需要调用外部命令

s="/a/b/c/d/filename.txt"
t=${s%/*}
t=${t##*/}
filename=${t}_${s##*/}

答案 4 :(得分:0)

举个例子:

 /a/1/b/c/d/file.txt
 /a/2/b/c/d/file.txt

限定file.txt并避免冲突的唯一可靠方法是将整个路径构建到新文件名中,例如

 /a/1/b/c/d/file.txt -> a_1_b_c_d_file.txt
 /a/2/b/c/d/file.txt -> a_2_b_c_d_file.txt

如果您确定所有文件都是通用的,例如,如果您知道所有文件都位于上面/a目录下的某个位置,则可以跳过部分开头:

 /a/1/b/c/d/file.txt -> 1_b_c_d_file.txt
 /a/2/b/c/d/file.txt -> 2_b_c_d_file.txt

要在每个文件的基础上实现此目的:

# file="/path/to/filename.txt"
new_file="`echo \"$file\" | sed -e 's:^/::' -e 's:/:_:g'`"
# new_file -> path_to_filename.txt

假设您希望在目录及其子目录中递归执行此操作:

# dir = /a/b
( cd "$dir" && find . | sed -e 's:^\./::' | while read file ; do
  new_file="`echo \"$file\" | sed -e 's:/:_:g'`"
  echo "rename $dir/$file to $new_file"
done )

输出:

rename /a/b/file.txt to file.txt
rename /a/b/c/file.txt to c_file.txt
rename /a/b/c/e/file.txt to c_e_file.txt
rename /a/b/d/e/file.txt to d_e_file.txt
...

以上是高度可移植的,基本上可以在sh的任何变体的任何Unix系统上运行(包含bashksh等。)