2


0

ファイル名とともに直接ディレクトリの名前を抽出する方法は?

完全なパスのようなファイルがあります

/a/b/c/d/filename.txt

http://en.wikipedia.org/wiki/Basename [basename]を実行すると、` filename.txt`が取得されます。 ただし、このファイル名は一意ではありません。

したがって、ファイル名を「d_filename.txt」として抽出できれば、より良いでしょう。

{immediate directory}_{basename result}

どうすればこの結果を達成できますか?

5 Answer


2


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

or

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


1


このコードは、スクリプトを実行したディレクトリから階層を再帰的に検索します。 あなたが投げたファイル名を処理するような方法でループをコーディングしました。スペース、改行などを含むファイル名

*:現在、ループは* not *に書き込まれ、このスクリプトが存在するディレクトリ内のファイルが含まれます。その下のサブディレクトリのみが参照されます。 これは、スクリプトが自身を処理に含めないようにする最も簡単な方法であったために行われました。 何らかの理由でスクリプトが存在するディレクトリを含める必要がある場合は、これに対応するように変更できます。

Code

#!/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


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


0


外部コマンドを呼び出す必要はありません

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


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
...

上記は非常に移植性が高く、本質的にはあらゆる s`の亜種( bash`、 `ksh`などを含む)のUnixシステムで実行されます。