現在のディレクトリ(名前にスペースを含む)のファイルを繰り返し、ファイルの最初の文字(まだ作成されていない場合)で新しいフォルダを作成し、移動するこのbashスクリプトを実行しようとしています。そのフォルダにファイルを置きます。これは私のコードです。
for i in `/bin/ls | xargs`
do
dir=`echo "$i" | cut -c 1 -`
mkdir -m777 -p "$dir"
mv "$i" "$dir"
done
この問題は、ファイル内の各単語を別々のファイルとして扱うため、フォルダを正しく作成してもファイル名を見つけることは、ファイル名だけを見つけるためにファイルをそのフォルダに移動できないことです。実際のファイルの最初の単語。同様の質問に対する他の答えを見てみましたが、これが私が得ることができる最も近い答えです。
編集:/bin/ls | xargs
@steeldriverの提案に従って、「for i in」を「for i in *」に変更し、元の問題を解決しましたが、次のエラーが発生しました。
mv: cannot move '`' to a subdirectory of itself, '`/`'
mv: invalid option -- ' '
mv: missing destination file operand after '-'
mv: invalid option -- '.'
mv: invalid option -- ')'
mv: invalid option -- '+'
mv: cannot move ''$'\340' to a subdirectory of itself, ''$'\340''/'$'\340'
mv: cannot move ''$'\303' to a subdirectory of itself, ''$'\303''/'$'\303'
mv: cannot move ''$'\305' to a subdirectory of itself, ''$'\305''/'$'\305'
mv: invalid option -- '1'
一部のファイルはASCII以外の文字で始まるようです(ファイルが多すぎて内容を見ることができません)。このような状況に対処するためのソリューションはありますか?
答え1
名前にスペースを含むファイルを繰り返すには、シェルで十分であるため、次を呼び出す必要はありませんls
。
for i in * # * replaces the complex (and unquoted) `/bin/ls | xargs`
do
dir=${i%"${i#?}"} # replaces the slow subshell `echo "$i" | cut -c 1 -`
echo "$i" # just to show that an * is enough (and accepts spaces).
done
リストされているすべてのファイル(ディレクトリを含む)を処理するには、ファイル名がファイル(ディレクトリではない)であることを確認し、ディレクトリを作成する前にそのディレクトリが存在しないことを確認する必要があります。
for i in *
do
if [ -f "$i" ]; then
dir=${i%"${i#?}"}
if [ ! -d "$dir" ]; then
mkdir -m777 -p "$dir"
fi
mv "$i" "$dir"
if [ "$?" -ne 0 ]; then
echo "An error occurred moving file \"$i\" to dir \"$dir\""
fi
fi
done
答え2
GNU Parallelを使用すると、次のようになります。
parallel 'mkdir -p {=s/(.).*/$1/=}; mv {} {=s/(.).*/$1/=}' ::: *
(編集:ディレクトリではなくファイルを要求したことを確認しました。/削除されました。)