フォルダで実行されるシェル機能があります(私の場合は、* .eps`ファイルを見つけて空の枠なしでpdfに変換します)。次の関数でこれを抽象化してみましょう。
function do_here() {
echo $(pwd)
}
ROOT_PATH
私はルートパスが与えられたディレクトリとパスを繰り返し、do_here
各リーフで作業する賢明な方法を探しています。象徴的な葉があるかもしれませんが、現時点ではこの要件はプラスのようです。
理由は次のとおりです。
ROOT_PATH
ディレクトリを参照するには、別名を使用してくださいto_path
。- ランニング
cd $to_path
- ランニング
do_here
- ステップ2に進みます。
手順1でディレクトリパスのリストを取得する方法がわかりません。
答え1
Bashは設定されている**
場合、再帰ワイルドカードもサポートします。shopt -s globstar
.globをサフィックスとして使用すると、ディレクトリのみがインポートされます/
。dotglob
名前がドットで始まるディレクトリを見逃さないように追加されました。
例えば
#!/bin/bash
shopt -s globstar
shopt -s dotglob
do_here() {
echo "working in $(pwd)...";
}
# cd ROOT_PATH
for d in **/; do (
cd "$d"
do_here
)
done
**
シェルの仕組み、つまりディレクトリツリー内のシンボリックリンクにはいくつかの違いがあります。ツリーに他のディレクトリへのリンクが含まれている場合は、少なくともいくつかのバージョンのBashがツリーの範囲外になり、それに従います。 (「記号の葉」がどういう意味なのかよく分からないので、それが問題なのかはわかりません。)
答え2
ディレクトリ内のすべてのファイルを取得するのと同じように、すべてのディレクトリを取得するには、次のものを使用できます。ワイルドカード;その後、ループを使用してfor
結果を繰り返し、サブシェル(( commands in subshell )
)またはpushd
/スタックpopd
のディレクトリを起動します。たとえば、
#!/usr/bin/zsh
for directory in **/*(ND/) ; do
print -r -u2 Working on ${directory}
( # do in subshell, so that `cd` doesn't affect
# the next iteration
cd -- "${directory}" && \
do_here # && : only if `cd` succeeded, do `do_here`
) || {
print -r -- "${directory} failed" >&2 | \
logger -p user.err
}
done
それを分解しよう
for directory in **/*(ND/) ; do
# ^ ^---+---^ ^ ^ ^^^
# | | | | ||\ *(/) extended glob: match directories
# | | | | |\- *(N) extended glob: null glob, i.e., don't fail if
# | | | | | nothing matches
# | | | | \-- *(D) extended glob: include directories starting with
# | | | | ".", i.e., normally hidden dirs
# | | | \---- * glob operator
# | | \------- **/ apply the following globbing recursively
# | |
# | \---------------- "loop variable": `directory` gets set to each result,
# | consecutively
# |
# \---------------------- for {variable name} in {list-generating expression} :
# for loop