000 から 10 までの番号のディレクトリの中で、存在するディレクトリにのみ subdir ディレクトリを作成する方法を紹介します。
状況設定
仕事で以下のようなケースにでくわしました。
3桁の数字で構成されるディレクトリが多数あり、その全ての下にsubdirというディレクトリを作成してください。ただし、数字は001~100まであり、基本連番ですが、中には歯抜けの数字も存在します。その場合、歯抜けの部分は作成しないでスキップしてください。
例として以下の状況を想定します。001は存在しているため、001/subdir は作成するが、 002は存在しないため002を作らずスキップする という状況です。
// 002は存在していないため、subdirを作成しない
.
├── 000
├── 001
├── 003
└── 010
ディレクトリを作るコマンドである mkdir には正規表現を使うためのオプションが存在しないため、別のコマンドと組み合わせて使う必要があります。
方法1: for ループと条件分岐を使う方法
結論をワンライナーで書くと、
for i in $(seq -w 0 100); do [ -d "$i" ] && mkdir -p "$i/subdir"; done
for i in $(seq -w 0 100)
:seq
コマンドは、指定された範囲の数値を生成します。-w
オプションを使うと、ゼロパディングされた出力が得られます。つまり、000
から100
までの3桁の数値が生成されます。
[ -d "$i" ]
:- 条件分岐のテストコマンドです。
-d
オプションは、指定されたパスがディレクトリであるかどうかを確認します。
- 条件分岐のテストコマンドです。
&& mkdir -p "$i/subdir"
:&&
は前のコマンドが成功した場合にのみ次のコマンドを実行するオペレーターです。ここでは、指定されたディレクトリが存在する場合にのみmkdir -p
コマンドが実行され、subdir ディレクトリが作成されます。
方法 2: find コマンドを使用
find . -maxdepth 1 -type d -regex '\./[0-9]\{3\}' -exec mkdir -p {}/subdir \;
find . -maxdepth 1 -type d
:find
コマンドは、指定されたパス(この場合は現在のディレクトリ.
)内で検索を行います。-maxdepth 1
は検索の深さを1に制限し、現在のディレクトリの直下のみを検索対象とします。-type d
はディレクトリのみを対象とするオプションです。
-regex '\./[0-9]\{3\}'
:-regex
オプションは、正規表現を使用して一致するパスを検索します。'\./[0-9]\{3\}'
は現在のディレクトリ内の3桁の数字からなるディレクトリを指定しています。[0-9]\{3\}
は任意の3桁の数字を表します。
-exec mkdir -p {}/subdir \;
:-exec
オプションは、検索結果に対して指定したコマンドを実行します。{}
は検索結果のディレクトリに置き換えられます。mkdir -p {}/
subdir は各ディレクトリに対して subdir ディレクトリを作成するコマンドです。
方法 3: xargs コマンドを使用
seq -w 0 100 | xargs -I {} bash -c '[ -d "{}" ] && mkdir -p "{}"/subdir'
seq -w 0 100
:seq
コマンドで000
から100
までの数値を生成します。
xargs -I {} bash -c '[ -d "{}" ] && mkdir -p "{}"/subdir'
:xargs
コマンドは、標準入力から読み取ったデータを引数として他のコマンドに渡します。-I {}
はプレースホルダーとして{}
を使用し、各入力行ごとにコマンドを実行します。bash -c '[ -d "{}" ] && mkdir -p "{}"/subdir'
は、各数値についてディレクトリの存在をチェックし、存在する場合にのみ subdir ディレクトリを作成します。- bash -c の-cオプションは、後続の”で囲まれた文字列をコマンドとして実行します。
方法 4: while ループを使用
i=0; while [ $i -le 100 ]; do printf -v dir "%03d" $i; [ -d "$dir" ] && mkdir -p "$dir/subdir"; i=$((i+1)); done
i=0
:- カウンタ変数
i
を初期化します。
- カウンタ変数
while [ $i -le 100 ]; do ... done
:while
ループは、カウンタ変数i
が100
以下の間、ループを実行します。
printf -v dir "%03d" $i
:printf
コマンドを使用して、カウンタ変数i
をゼロパディングされた3桁の文字列に変換し、変数dir
に格納します。
[ -d "$dir" ] && mkdir -p "$dir/subdir"
:- ディレクトリの存在を確認し、存在する場合にのみ subdir ディレクトリを作成します。
i=$((i+1))
:- カウンタ変数
i
をインクリメントします。
- カウンタ変数
結論
mkdirに正規表現を使うオプションが存在しないため、今回のようなケースでは複数のコマンドを組み合わせてコードを書き必要があります。
このコードを応用すると、今度はsubdirの削除もすぐに書くことが可能です。その方法は以下の記事をご参照ください。
リンク