私は最も基本的なタスク、つまり特定のフォルダ内のすべてのファイルに対して1つ以上のコマンドを実行しようとしています。
この場合、macOSpstopdf
コマンドを使用してEPSファイルをPDFに変換します。
#!/bin/zsh
FILES=$(find "/Users/Ben/Pictures/Stock Illustrations" -type f)
for f in "$FILES"
do
echo "$f"
pstopdf "$f"
done
echo "$f"
pstopdf
すべてのファイルの正しいリストを生成しますが、それ自体が一見で始まる2番目のファイルのリストを取得しますが、残りのファイルは正しくリストされますFile name too long: /Users/Ben/Pictures/Stock Illustrations/Flock wallpaper.eps
。
ただし、このpstopdf
コマンドはPDFファイルを生成しません。
**各コマンドがファイル名のリストを生成することを知るために、echo
コマンドをコメントアウトしてみました。pstopdf
ターミナルで実行すると、pstopdf <file.eps>
CLIからの出力は取得されません(ファイル名がリストされていません)、ファイルが処理されPDFファイルが生成されます。
私はコマンドxargs
で利用可能であると言いますがfind
、特に複数のコマンドや他のロジックのオプションを提供し、読みやすくするため、パラメータ付きループの構造化アプローチを好みます。
ここにも同様の質問があります。for..inを実行してタッチすると、「ファイル名が長すぎます」というメッセージが表示されます。
しかし、答えがどのように適用されるのか理解していません。 「または一つずつタッチしてください」(私が欲しいもの)となっていますが、そうすれば次のようになります。
FILES=/Users/Ben/Pictures/Stock\ Illustrations/*
「該当するファイルやディレクトリがありません」というメッセージが表示されます。
答え1
FILES=$(find "/Users/Ben/Pictures/Stock Illustrations" -type f) for f in "$FILES"
リンクされた投稿に示すように、$FILES
ここにはすべてのファイル名を含む文字列があります。ファイルが十分な場合、単一のファイル名が長すぎます。名前がほんの数しかない場合は、名前に改行文字を含むファイルにアクセスしようとします。
find
ここでは自分を呼ぶ方が良いですpstopf
。
$ find "/Users/Ben/Pictures/Stock Illustrations" -type f -print -exec pstopdf {} \;
find出力にシェルループを使用するには、次の手順を実行する必要があります(Bashではzshについて言及していません)。
set -f # disable globbing
IFS=$'\n' # set IFS to just the newline (Bash/ksh/zsh, not POSIX)
files=$(find "/Users/Ben/Pictures/Stock Illustrations" -type f)
for f in $files; do
echo "$f"
pstopdf "$f"
done
またはfind ... -print0 | while IFS= read -r -d '' f; do ...; done
Bashで使用してください。
または、for f in "/Users/Ben/Pictures/Stock Illustrations"/**/*; do ...
Bash(使用shopt -s globstar
)、ksh、またはzsh(詳細はシェルによって多少異なります)。
どちらのシェルソリューションも改行文字を含むファイル名に問題があります。あなたにはそのような問題がないことを願っていますが、残念ながら改行文字は許可されています。
答え2
FILES=$(find "/Users/Ben/Pictures/Stock Illustrations" -type f)
はスカラー変数を割り当てるための構文(zshまたは他のKorn様シェル)なので、$FILES
aに対して1つの値のみを取得します。これはaのフル出力ですfind
。
ここでは、次のようになります。
files=( ${(0)"$(find "/Users/Ben/Pictures/Stock Illustrations" -type f -print0)"} )
$files
見つかった各ファイルを要素とする配列になりたい場合find
。find
ゼロで区切られたリストを提供し、0
パラメータ拡張フラグを使用してそれらをsに分割する必要があります0
。これは、ファイルパスには現れない唯一のバイト値だからです。
しかし、ここではglobが同じことをすることができるので、find
そうする必要はありません。zsh
files=( "/Users/Ben/Pictures/Stock Illustrations"/**/*(ND.) )
再帰**/*
ワイルドカードと.
同じです-type f
。
これを繰り返すには、次のものが必要です。
for f in $files; do
print -r -- $f
pstopdf $f
done
または:
for f ($files) {
print -r -- $f
pstopdf $f
}
"$files"
配列の要素を最初の文字$IFS
(kshと同じ)に"${files[*]}"
関連付けるので、これは望ましくありません。 zshで引用符で$files
囲まれていないループを使用して、配列のnull以外の要素を繰り返します。"${files[@]}"
すべての要素を繰り返しますが、配列に空の要素が含まれていないことが保証されるため、ここでは違いはありません。