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