web-dev-qa-db-ja.com

'/'文字を含むtxtファイルから名前でディレクトリを作成します

このようなテキストを含む.txtファイルがあります

A1/B1/C1
A2/B2/C2 
A3/B3/C3

各行の.txtファイルを読み取り、最初のWord(A1、A2、A3)に基づいてディレクトリを作成するスクリプトが必要です

次のようなスクリプトを作成しました。

file="test.txt"
while IFS='' read -r line
do
    name="line"
    mkdir -p $line
done <"$file"

実行中にディレクトリA1が作成され、次にサブディレクトリB1およびC1も作成されます。同じことが別の行(A2 *およびA3 *)でも発生します

A1、A2、A3ディレクトリのみを作成するにはどうすればよいですか?

「/」文字を含むA1/B1/C1のような名前を作りたくありません。 「/」文字の前にWordを取り、ディレクトリ名にしたいだけです。ちょうど「A1」「A2」「A3」。

8
maulana

各行の1stスラッシュ-cutelimitedフィールドだけをdして、リストをmkdirに渡すことができます。

mkdir $(<dirlist.txt cut -d/ -f1)

実行例

$ cat dirlist.txt 
A1/A2/A3
B1/B2/B3
C1/C2/C3
$ ls
dirlist.txt
$ mkdir $(<dirlist.txt cut -d/ -f1)
$ ls
A1  B1  C1  dirlist.txt

リストにhuge個のディレクトリ名が含まれている場合、 ARG_MAX の問題が発生する可能性があります。この場合はGNU parallelInstall parallel またはxargsは次のとおりです。

parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir

parallelでカバーされていますが、ディレクトリ名にスペースが含まれている場合、xargsのアプローチは機能しません。行区切り文字として\0を使用するか、単にxargsに改行文字のみを入力するように指示することができます- Martin Bonner )代わりに:

xargs -0a<(<dirlist.txt tr \\{n,0} | cut -d/ -f1 -z) mkdir # \\{n,0} equals \\n \\0
xargs -d\\n -a<(<dirlist.txt cut -d/ -f1) mkdir

いずれかのフィールドに改行文字が含まれている場合、「真の」行末を識別し、それらの改行文字のみをたとえば\0。これはawkの場合ですが、ここでは取得しすぎだと感じています。

13
dessert

readIFS='/'を設定し、最初の各フィールドを個別の変数firstに割り当て、残りのフィールドを変数restに割り当てて、最初のフィールドの値を操作する必要があります。 (または、単一の配列にread -ar arrayを使用し、最初のフィールドの値に"${array[0]}"を使用できます。)

while IFS='/' read -r first rest;
do
    echo mkdir "$first" 
done < test.txt

またはそれが好きな人のための単一行で:

<test.txt xargs -d'\n' -n1 sh -c 'echo mkdir "$'{1%%/*}'"' _

または、すべてのディレクトリを一括で作成します。

<test.txt xargs -d'\n' bash -c 'echo mkdir "$'{@%%/*}'"' _

ANSI-C引用符$'...' は、特殊文字を含むディレクトリ名を処理するために使用されます。

末尾の_(任意の文字または文字列)はbash -c '...'に対してargv [0]になり、$@には1から始まる残りのパラメーターが含まれます。これがないと、2番目のコマンドでmkdirへの最初のパラメーターが失われます。

${1%%/*}Shell(POSIX sh/bash/Korn/zsh)パラメーター置換展開 を使用して、スラッシュに続く可能な限り長い一致を削除します。 xargsによって読み取られた行;

追伸:

  • echoの前にあるmkdirを削除して、これらのディレクトリを作成します。
  • リストが-d'\n'ewlineの代わりにNUL文字で区切られている場合は、-0\nに置き換えます(ディレクトリ名に改行が埋め込まれている場合)。
10
αғsнιη

test.txtの内容:

A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3

A[123]フォルダーを作成するスクリプト:

file="test.txt"
while read -r line ; do
   mkdir "${line%%/*}"
done < "$file"

lsの出力:

A 12"x4" dir
A1
A2
A3
6
xiota

質問の入力例に示されているような単純なケースでは、cutを使用し、mkdirを介してxargsに出力を渡すだけです。

cut -f1 -d '/' file.txt | xargs -L1 mkdir 

ディレクトリ名にスペースが含まれる場合の処理​​では、-d '\n'をオプションのリストに追加できます。

$ cat input.txt 
A 1/B 1/C 1
A 2/B 2/C 2
A 3/B 2/C 2
$ cut -f1 -d '/' input.txt | xargs -d '\n' mkdir 
$ ls
A 1  A 2  A 3  input.txt

@OleTangeがコメントで示唆しているA 12"x4" dir/B b/C cなど、より複雑なバリエーションの場合は、awkを使用して、改行区切りリストではなくヌル区切りリストを作成できます。

awk -F'/' '{printf  "%s\0",$1}' input.txt |  xargs -0 mkdir

コメントの@dessertは、printfの代わりにcutを使用できるかどうか疑問に思っていました。技術的には、たとえば、印刷文字列を3文字の幅に制限することで使用できます。

xargs -d '\n' printf "%.3s\n"  < input.txt | xargs -L1 mkdir 

最もクリーンな方法ではありませんが、printfを使用できることが証明されています。もちろん、ディレクトリ名が3文字より長くなると、これは問題になります。

4

perlを使用:

Perl -ne 'mkdir for /^(\w+)/' list.txt

または

Perl -ne 'mkdir for /^([^\/]+)/' list.txt

dir-namesでスペースを受け入れたい場合

2
user216043

GNU Parallelはこのタスクには過剰かもしれませんが、各行で他のことをしようとするなら、役に立つかもしれません:

cat myfile.txt | parallel --colsep / mkdir {1}
parallel -a myfile.txt --colsep / mkdir {1}

次のような入力を正しく処理します。

A 12"x4" dir/B b/C c
0
Ole Tange