名前にスペースが含まれるファイルのリストからディレクトリを作成します。

名前にスペースが含まれるファイルのリストからディレクトリを作成します。

ファイルのリストを含むディレクトリがあります。これらのファイルはすべて名前にスペースがあります。

拡張子を除いて、ファイル名を含む各ファイルのディレクトリを作成したいと思います(すべてのファイルの拡張子は.docです)。

たとえば、

私のディレクトリの内容

first file.doc 
second file.doc 
third file.doc

予想される結果

first file/first file.doc 
second file/second file.doc
third file/third file.doc

作成するディレクトリ名を確認するには、次のコマンドを使用します。

find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}'

結果は次のとおりです。

first file
second file
third file

各項目に対してディレクトリを作成する必要があることを理解してください。

私は成功せずに次のことを試しました。

find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}' -exec mkdir '{}' \;
#error with awk: it cannot open the file -exec because it does not exist

mkdir `find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}'`
#it creates several directories per name because there are spaces in the names

mkdir `"find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}'"`
#-bash: find . -maxdepth 1 -name *.doc | awk -F .doc '{print }': command not found

mkdir "`find . -maxdepth 1 -name "*.doc" | awk -F ".doc" '{print $1}'`"
#it tries to create a unique directory with all the file names as a single name, which is not good of course

可能であれば、ファイル名からすべてのスペースを削除したいのですが、プロジェクトの制約に合うようにしてください。

これらのディレクトリを作成できるようになったら、一致するディレクトリ内のすべてのファイルを移動する方法を理解する必要があります。これはすべて1つのコマンドで実行できます。

私はbashとRedHat 2.6を使用しています。

ご協力ありがとうございます。ローラン

答え1

そしてzsh

mkdir -p -- *.doc(:r)

または:

for f (*.doc) {
  mkdir -p -- $f:r &&
    mv -- $f $f:r/
}

同等bash(すべてのPOSIXシェルでも動作しますがzsh):

for f in *.doc; do
  mkdir -p -- "${f%.*}" &&
    mv -- "$f" "${f%.*}/"
done

(隠しファイルは含まれませんのでご注意ください)

答え2

ファイル/ディレクトリ名のスペースは、名前が正しく引用されている限り大丈夫です。

find . -maxdepth 1 -name "*.doc" | while IFS= read -r f; do 
    mkdir -- "${f%.doc}"; 
done

答え3

cd /path/to/dir
(   set -- *\ *
    printf 'd="%s" ; mkdir ./"${d%%.doc}"\n' "$@"
) | . /dev/stdin

シェルglobを使用してサブシェルのパラメータを設定し、printfを使用してパイプにデータを提供できます。パイプをスクリプトソースとして使用します。

各ディレクトリのファイルを移動するには、次の手順を実行します。

cd /path/to/dir
(   set -- *\ *
    printf 'f="%s" ; d="${f%%.doc}"
        mkdir ./"$d" ; echo "mv ./\"$f\" ./\"$d\"/\"$f\""\n' "$@"
) | . /dev/stdin

注:コミットする前に出力をテストしたいので、意図的に上記の内容をエコーに制限しました。

修正済み - printfに2%の割合を使用することを忘れました。

ところで、私はこれをテストしました:

% printf 'touch ./"%s file.doc"\n' first second third fourth fifth |
    . /dev/stdin
% ls
> fifth file.doc  first file.doc  fourth file.doc  second file.doc  third file.doc

% ( set -- *\ *
    printf 'f="%s" ; d="${f%%.doc}"
    mkdir ./"$d" ; mv ./"$f" ./"$d"\n' "$@"
) | . /dev/stdin

% ls
> fifth file  first file  fourth file  second file  third file

% cd fifth\ file ; ls
> fifth file.doc

関連情報