从名称中带有空格的文件列表创建目录

从名称中带有空格的文件列表创建目录

我有一个目录,其中包含文件列表。所有这些文件的名称中都有空格。

我想为每个文件创建一个目录,其中包含文件名,但扩展名除外(所有文件的扩展名都是 .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

如果可以的话,我会删除文件名中的所有空格,但我需要保留它们以适应项目限制:/

一旦我可以创建这些目录,我将必须弄清楚如何移动其匹配目录中的所有文件。这一切都可以通过一个命令完成,我会接受的:)

我正在使用 bash 和 RedHat 2.6。

感谢您的帮助。洛朗

答案1

zsh

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

或者:

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

等效bash的(尽管它也适用于所有 POSIX shell 和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

您可以使用 shell glob 设置子 shell 的参数,然后使用 printf 和 为管道提供数据。将管道作为脚本源。

如果你想移动每个目录中的文件:

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

注意:我故意用 echo 来限制上面的内容,因为我希望您在投入之前测试输出。

已修复 - 我忘记对 printf 使用两个 % 百分比。

顺便说一句,我对此进行了测试:

% 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

相关内容