'/'文字を含むtxtファイルから名前を付けてディレクトリを作成する


8

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

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

各行の.txtファイルを読み取り、最初の単語(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のような名前を作りたくありません。「/」文字の前の単語を取り、それをディレクトリ名にしたいだけです。「A1」「A2」「A3」だけです。

回答:


13

各行のスラッシュで区切られたフィールドだけをリストにしてcut1次のように指定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

リストに膨大な数のディレクトリ名が含まれている場合、ARG_MAXの問題が発生する可能性があります。この場合は、GNU または次のように使用します。parallel 並列インストールxargs

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

一方でparallel、それはカバーされている、xargsディレクトリ名にスペースが含まれている場合のアプローチはない仕事はします-あなたはいずれかを使用することができ\0、単純に指示行区切り文字として、またはxargs(によって提案されたように改行文字の入力を分割のみにマーティン・ボナー)の代わりに:

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、ここではあまりにも多くのことを理解していると思います。


なぜxargs -a<(....)ではなく<dirlist.txt cut -d/ -f1 | xargs
Martin Bonnerがモニカをサポートする

1
@MartinBonner明確にしていただきありがとうございます。これは実際に私のtrアプローチよりも簡単parallelです。デフォルトでカバーされていることに気づきました。
デザート

@MartinBonner パイプではなく、なぜかとxargs -a<(....)いうと、私はこの方法が好きなので、単純です。:)
デザート

@AndreaCorbelliniああ、わかりました。<(...)スペースにも役立つので、間違いなくより良い選択です。とにかく、このファイル記述子を誰も使用していなかったと思います。
デザート

さらに興味深いことに@MartinBonner:なぜcut <dirlist.txtだけではなくcut dirlist.txt
デザート

11

IFS='/'for を設定し、read最初の各フィールドを個別の変数に割り当て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の引用は、$'...'特殊文字を含むディレクトリ名に対処するために使用されます。

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

${1%%/*}使用してシェル(POSIX SH / bashの/コーン/ zshの)パラメータ置換拡張、スラッシュを削除し可能な限り長いマッチはによって読み込まれた行であることに渡すパラメータの終わりまで何続いxargsの

PS:

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

6

の内容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

次のような入力をどのように処理しますA 12"x4" dir/B b/C cか?
Ole

Ole Tange-そのコメントは質問の対象外です。
DocSalvager 2018年

4

質問の入力例に示されているような単純なケースの場合、使用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

A 12"x4" dir/B b/C cコメントの@OleTangeで提案されているような、より複雑なバリエーションの場合awkは、改行で区切られたリストの代わりにnullで区切られたリストを作成するように頼むことができます。

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文字より長くなると問題になります。


次のような入力をどのように処理しますA 12"x4" dir/B b/C cか?
Ole

@OleTange編集を参照してください。
Sergiy Kolodyazhnyy

2

Perlを使用:

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

または

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

dir-namesにスペースを入れたい場合


1
perl -ne 'mkdir for /^([^\/]+)/' list.txtディレクトリ名のスペースをカバーします。最後にPerlを学ぶ必要があります–ありがとうございます!
デザート

0

GNU Parallelはこのタスクにはやり過ぎかもしれませんが、各行に対して他のことを行う場合は、それが役立つことがあります。

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

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

A 12"x4" dir/B b/C c
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.