1

次のような構造のプレーンテキストでフォルダーを作成したい:

Folder
| Subfolder
| | Deeper-subfolder
| Subfolder

次のような基本コマンドを使用することを考えたところ、ディレクトリ構造を作成するmkdir投稿: Bash スクリプトが見つかりましたが、次のような構造を記述する必要があります。

Folder
Folder/subfolder
Folder/subfolder/deeper-subfolder
Folder/subfolder

したがって、で使用される正規表現を変更する必要があります。

sed '/^$/d;s/ /\//g' struct.txt | xargs mkdir -p

これを行うには、どの bash コマンドを使用できますか?

4

3 に答える 3

4

純粋な sed の使用:

#!/bin/sed -f

x
G
: loop
s:\([^/]*\)/*\(.*\n\)\([^|]*\)|\s:\2\3\1/:
t loop

s/.*\n//
s:/*$::
h

このためには、ホールド スペース (補助バッファー) を使用して、以前のディレクトリ パスを格納する必要があります。次に、ホールド スペースからディレクトリを削除し、それらをそれぞれの | に置き換えることができます。より詳細な説明は次のとおりです。

このスクリプトは、すべての行に対して実行されます。まず、ホールド スペースとパターン スペースを交換 ("x") します。最初は、ホールド スペースは空ですが、最初の行の後、ホールド スペースには以前のディレクトリ パスが含まれます。それらを交換することにより、以前のディレクトリをロードし、現在の新しいディレクトリをホールド スペースに保存します。

次に、新しいディレクトリ名を以前のディレクトリ パスに追加します (ただし、どちらも改行で区切られます)。これに使用されるコマンドは「G」です。

| ごとにループする必要があります。私たちが見つけたキャラクター。これを行うのはトリッキーな部分なので、我慢してください。現在のパターン空間に次のものがあるとします

Folder/subdir
| | deeper-subdir
  1. まず、 は最初のスラッシュの前のすべてに一致し、それをキャプチャします (つまり、最初のキャプチャ グループであるため\([^/]*\)名前が付けられた「変数」に格納します)。\1
  2. 次に、スラッシュをスキップします:/*
  3. 改行まで (含む) すべてをキャプチャし、 capture に格納します\2\(.*\n\)
  4. 最初の前のすべてをキャプチャ | キャラクターとキャプチャーに保存\3: \([^|]*\)
  5. | をスキップ 文字の後にスペース文字:|\s

これで、キャプチャは次のようになります。

  1. フォルダ
  2. サブディレクトリ\n
  3. 3.

キャプチャを並べ替えて別のスラッシュを追加する行を再生成するだけで、次のようになります。

subdir
Folder/| deeper-subdir

その後、前の「s」コマンドが成功した場合にのみ「ループ」ラベルに戻る条件付き分岐コマンド「t」があります。つまり、文字列の準備ができたら (| がなくなると)、ループを終了してコードを続行できます。

例に従って、次の反復にはキャプチャが含まれます。

  1. サブディレクトリ
  2. \n
  3. フォルダ/

ループの後、最初の代替コマンドは、新しいディレクトリが入力されていないパスを含む最初の行を削除します (つまり、新しいディレクトリは前のディレクトリよりも「浅い」です)。

最後の代替コマンドは、行末からスラッシュをすべて削除し、最後のコマンドはホールド コマンド ("h") で、現在生成されているパスをホールド スペースにコピーするため、次の行ですべてを繰り返すことができます。

これが役立つことを願っています=)

于 2012-09-28T18:19:47.357 に答える
1

提供した sed スクリプトの正規表現を変更するだけでは、それを行うことはできません。その理由は、参照した例では、ディレクトリ構造を持つファイルのすべての行に、ディレクトリを作成するのに十分な情報が含まれていたためです。あなたの例では、いくつかのデータ操作を行う必要があり、親フォルダーを追跡します。これはより複雑になります..必要がない限り、複雑さを導入することは好きではありません。

于 2012-09-28T14:59:43.437 に答える
0

次のスクリプトで実行できます。

アイデアは、ディレクトリ名の「スタック」を維持し、ラインにあるパイプの数に基づいてプッシュまたはポップすることです。

(このスクリプトは、入力ファイルが整形式であり、ファイル名に空の行や特殊文字が含まれていないことを前提としています。)

#!/bin/bash

file=$1

# helper function to create a directory from an array
mkDirs(){
    IFS=/ dir="$*"
    echo "mkdir -p $dir"
}

declare -a stack=()
while read line
do
    dirName="${line##*| }"
    pipes="${line//[^|]/}"
    num_pipes="${#pipes}"
    diff=$(( ${#stack[@]} - $num_pipes ))
    if [[ "$diff" -ne 0 ]]
    then
        # create the directory
        mkDirs "${stack[@]}"
        while (( "$diff" != 0 ))
        do
            unset stack[${#stack[@]}-1] # pop off stack
            diff=$(( ${#stack[@]} - $num_pipes ))
        done
    fi
    stack=("${stack[@]}" "$dirName") # push on stack
done < "$file"
mkDirs "${stack[@]}"

例:

$ cat struct.txt
Folder
| Subfolder
| | Deeper-subfolder
| Subfolder
| | SubSubFolder
| | | Another
| | | | AnotherChild
| | | YetAnother
Folder2

$ run.sh struct.txt
mkdir -p Folder/Subfolder/Deeper-subfolder
mkdir -p Folder/Subfolder/SubSubFolder/Another/AnotherChild
mkdir -p Folder/Subfolder/SubSubFolder/YetAnother
mkdir -p Folder2
于 2012-09-28T15:44:42.130 に答える