我有一个具有以下结构的目录:
example
├───1
│ └───01-01-2015.txt
├───2
│ └───02-02-2016.txt
├───3
│ └───03-03-2017.txt
└───script.sh
我正在尝试编写一个脚本,该脚本将查找所有 .txt 文件,并在它们之外创建一个新文件夹,其名称基于特定文件夹中 .txt 文件的名称。
所以结果将是:
example
├───1
│ ├───01-01-2015
│ └───01-01-2015.txt
├───2
│ ├───02-02-2016
│ └───02-02-2016.txt
├───3
│ ├───03-03-2017
│ └───03-03-2017.txt
└───script.sh
因此,在文件夹“3”子文件夹“03-03-2017”中,在文件夹“2”子文件夹“02-02-2016”等中。
我知道查找所有 .txt 文件非常简单,但无法弄清楚如何将其与创建目录并为每个搜索结果执行子字符串相结合。
提前致谢!!
答案1
find example -name \*.txt | sed 's/\.txt$//' | xargs -n 1 mkdir
警告:这需要你的路径不是包含换行符。
编辑:如果您使用 GNU 工具,请参阅 terdon 的评论。
答案2
我会为此使用 bash 循环:
for i in **/*.txt; do mkdir "${i%.txt}"; done
如果我在你的例子上运行这个,我会得到:
$ tree
.
├── 1
│ └── 01-01-2015.txt
├── 2
│ └── 02-02-2016.txt
└── 3
└── 03-03-2017.txt
3 directories, 3 files
$ shopt -s globstar
$ for i in **/*.txt; do mkdir "${i%.txt}"; done
terdon@oregano foo $ tree
.
├── 1
│ ├── 01-01-2015
│ └── 01-01-2015.txt
├── 2
│ ├── 02-02-2016
│ └── 02-02-2016.txt
└── 3
├── 03-03-2017
└── 03-03-2017.txt
6 directories, 3 files
globstar
是一个 bash 选项,解释如下man bash
:
环球星
**
如果设置,路径名扩展上下文中使用的模式将匹配所有文件以及零个或多个目录和子目录。如果模式后跟/
,则仅目录和子目录匹配。
因此,在使用 启用它后shopt -s globstar
,该模式**/*.txt
将查找名称以 结尾的所有文件(或目录).txt
。
shell语法${i%.txt}
用于删除子字符串。一般格式是${variable%string}
它将string
从变量末尾删除第一个实例。因此,${i%.txt}"
将是文件名(包括父目录)减去.txt
.因此,[将其传递给mkdir
将创建您想要的目录。
就我个人而言,我发现上面的语法更简单,但以下是如何使用find
:
find . -name '*.txt' -exec sh -c 'mkdir ${0%.txt}' {} \;
在这里,-exec command {}
将替换{}
为每个结果find
,然后command
对其运行。由于此处的命令是对 的调用sh -c
,因此sh
将采用{}
作为其第零个位置参数$0
。因此,我们然后运行与上面解释的相同的 shell 替换来创建目录。