シェル変数に保存されているパスのリストがありますtmp
。たとえば、次のようになります。
/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S2_L001_I1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_I2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_I2.tar
パスの一致パターンに基づいて新しいディレクトリを作成したいと思います。上記の例では、ディレクトリをZRT834_9
作成し、そのディレクトリのファイルへのZRT207_1
ソフトリンクを作成したいと思います。tar
ZRT834_9
私の出力は次S1_L001_R1.tar
のようになりますS2_L001_I1.tar
。S1_L001_I2.tar
どうやってこれを達成できますか?
答え1
存在するzsh
:
files=(
/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S2_L001_I1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_I2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_I2.tar
)
# or files=(${(f)"$(<list.txt)"}) to get the file list from the non-empty
# lines of list.txt, or files=($=tmp) for word splitting the contents
# of a $tmp scalar variable according to the current value of $IFS.
for file ($files) {
dir=${file:h5:t}
mkdir -p -- $dir && ln -s -- $file $dir/
}
-comComponent1のヘッダーと結果の尾を${file:h5}
取得する位置です。または最後から数えることができます。5
h
$file
:t
${file:t3:h1}
¹ここ要素パスコンポーネントです。たとえば、コンポーネントは、、、、および../a//b///c/./d/e
です。与え、降伏する。 andを適用する前に、仕様への絶対パスの取得も参照してください。..
a
b
c
.
d
e
:h5
../a//b///c/.
:t
.
${file:A:h5:t}
:h5
:t
答え2
あなたの説明に基づいて、次の仮定が行われました。
- 変数
tmp
には、改行で区切られたファイル名のリストが含まれています。[1] - あなたは抽出したい五ファイル名のパス要素(たとえば、
ZRT834_9
およびZRT207_1
) - サブディレクトリがまだ存在しない場合は、このパス要素を使用してサブディレクトリを作成しようとします。
- ファイル名を新しく作成されたディレクトリにシンボリックリンクしようとしています。
#!/bin/bash
tmp="/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S2_L001_I1.tar
/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_I2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R1.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R2.tar
/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_I2.tar"
while read -r f ; do
d="$(echo "$f" | sed -E 's:^(/+[^/]+){4}/+([^/]*)/.*:\2:')"
[ -z "$d" ] && echo "Error: no fifth element in path: '$f'" && exit 1
mkdir -p "$d" || exit 1
ln -s "$f" "$d/"
done <<< "$tmp"
スクリプトsed
は拡張正規表現(オプション)を使用し-E
(ほぼ英語に翻訳されています)(最初の4つのグループ()をキャプチャグループ1としてキャプチャします(1つ以上のスラッシュの後に1つ以上のスラッシュ以外の文字が続く)。 。 1つ以上のスラッシュはキャプチャグループ2に入り、入力行全体をキャプチャグループ2()に置き換えます。{4}
/+[^/]+
[^/]+
\2
「1つ以上のスラッシュ」は、このようなパス名が完全に有効であるためです/foo/////////////////bar////baz
。追加/ sは無視されます。しかし、いくつかのプログラム(smbclient
例:スタートサーバー名の前に2つのスラッシュを使用しますが、ほとんどのプログラムではそうではありません。
[1] これには配列を使用する必要があります。例えば
#!/bin/bash
# double-quote each array element even though your sample
# data doesn't need to be quoted - because other filenames
# might contain white-space or shell metacharacters.
tmp=("/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_R1.tar"
"/abc/bcd/def/ZRT834/ZRT834_9/5678/S2_L001_I1.tar"
"/abc/bcd/def/ZRT834/ZRT834_9/5678/S1_L001_I2.tar"
"/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R1.tar"
"/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_R2.tar"
"/abc/bcd/def/ZRT207/ZRT207_1/5678/S1_L001_I2.tar")
for f in "${tmp[@]}" ; do
d="$(echo "$f" | sed -E 's:^(/+[^/]+){4}/+([^/]*)/.*:\2:')"
[ -z "$d" ] && echo "Error: no fifth element in path: '$f'" && exit 1
mkdir -p "$d" || exit 1
ln -s "$f" "$d/"
done
答え3
GNU sedは代替構造のbacklinkパラメータを使用してシェルコマンドを実行できます。
sed 's%.*/\([^/]*/\)[^/]*/[^/]*%mkdir -p "\1";ln -s "&" "\1"%e;d' <<<"$tmp"