私は与えられたパスの親ディレクトリのリストを提供できるbashスクリプトで利用可能なツールを探しています。
foo/bar/moocow
たとえば、出力したい入力があるとします。
foo
foo/bar
foo/bar/moocow
複数のパスを入力して独自の結果を得ることができれば良いでしょう。たとえば、次のようになります。
toolimlookingfor << EOF
dir1/file1
dir1/file2
foo/bar/moocow
EOF
出力:
dir1
dir1/file1
dir1/file2
foo
foo/bar
foo/bar/moocow
dirname
私が探しているものに近いが、直系の親だけを提供します。私は自分自身とすべての親の道を探しています。
答え1
/tmp
フォルダ内に新しいディレクトリを作成することに同意する場合は、findコマンドを使用できます。この方法では、一意のディレクトリ名のみを印刷することもできます。
#!/bin/bash
if [[ $# -eq 0 ]]; then exit; fi
mkdir -p /tmp/printnames
for i
do
mkdir -p /tmp/printnames/"$i"
done
cd /tmp/printnames
find * -type d -print
rm -r /tmp/printnames
したがって、一時ディレクトリ構造を作成し、検索を使用して移動できます。
答え2
標準Pythonスクリプトの使用pathlib
入力の代わりにパラメータを処理するモジュール:
#! /usr/bin/env python3
import sys
from collections import OrderedDict
from pathlib import Path
paths = OrderedDict() # to maintain ordering and skip duplicates
for arg in sys.argv[1:]:
path = Path(arg)
for subpath in reversed(path.parents):
# add the parents
paths[subpath.as_posix()] = subpath
# add the path itself
paths[path.as_posix()] = path
# we don't need '.' in the output
if '.' in paths:
paths.pop('.')
print('\n'.join(paths.keys()))
(これはループを介して標準入力を使用するように簡単に変更できますsys.stdin
。)
例:
% ./foo.py dir1/file1 dir1/file2 foo/bar/moocow
dir1
dir1/file1
dir1/file2
foo
foo/bar
foo/bar/moocow
答え3
このコードはこれを行います。一時ファイルを使用しません。スペースにはうまく機能しますが、改行文字はあいまいです(変更される\n
ように変更されます\0
)。\0
自動化されたプロセスで使用するには、それを使用する必要があります。\0
Unix ファイル名に含まれないことが保証される唯一の文字です。
単に再帰的に使用されます。dirnames
特定を削除/有効にすることでprintf
調整できます。上下に移動したり、ルートノード(.
または/
)を表示しないようにします。あなたの例ではルートノードが表示されていませんが、必要だと思います。これがなければ/a/b/c
出力はa/b/c
。
#!/bin/bash
function dirnames {
local input
local parent
input="$1"
if [[ "$input" == "" ]]
then
true
elif [[ "$input" == "." || "$input" == "/" ]]
then
printf '%s\n' "$input" #print the root node
else
#printf '%s\n' "$input" #print node (descending)
parent="$(dirname "$input")"
dirnames "$parent"
printf '%s\n' "$input" #print node (ascending)
fi
}
for d in "$@"
do
dirnames "$d"
done
使用例
%↳ ./dirnames a/b/c
.
a
a/b
a/b/c
%↳ ./dirnames /a/b/c
/
/a
/a/b
/a/b/c
%↳
このように動作させるには
%↳ ./dirnames a/b/c
.
a
b
c
%↳ ./dirnames /a/b/c
/
a
b
c
%↳
次に、ファイルを別の名前で保存してdirnames
実行しますsed -r -i '17 s/("[$]input")/"$(basename \1)"/' dirnames
。これで、各レベルの葉だけを出力するスクリプトが生成されます。
答え4
私の場合のように、末尾のスラッシュ(または他の区切り文字)が効果がある場合は、次の解決策が最も簡単で透明です。
pth='one/two/three'
sep='/'
# split string into array by separator
arr=($(echo $pth | tr $sep '\n'))
# loop over array and append
sub=''
for index in ${!arr[@]}
do
sub+="${arr[index]}$sep"
printf "$index \t ${arr[index]} \t $sub \n"
done
出力:
0 one one/
1 two one/two/
2 three one/two/three/