我有一个 .txt 文件,其中包含如下文本
A1/B1/C1
A2/B2/C2
A3/B3/C3
我想要一个脚本,读取 .txt 文件的每一行,然后根据第一个单词创建一个目录(A1、A2、A3)
我已经创建了这样的脚本:
file="test.txt"
while IFS='' read -r line
do
name="line"
mkdir -p $line
done <"$file"
当我运行它时,它会创建目录 A1,然后还会创建子目录 B1 和 C1。另一行(A2* 和 A3*)也会发生同样的情况
我应该怎么做才能仅创建 A1、A2、A3 目录?
我不想将名称改为 A1/B1/C1 之类的带有“/”字符的名称。我只想将“/”字符之前的单词作为目录名称。只需“A1”“A2”“A3”即可。
答案1
您可以只保留每行中以斜线分隔的cut
字段并将列表提供给:1
d
mkdir
mkdir $(<dirlist.txt cut -d/ -f1)
示例运行
$ cat dirlist.txt
A1/A2/A3
B1/B2/B3
C1/C2/C3
$ ls
dirlist.txt
$ mkdir $(<dirlist.txt cut -d/ -f1)
$ ls
A1 B1 C1 dirlist.txt
你可能会遇到最大参数如果你的列表包含巨大的目录名称的数量,在本例中使用 GNUparallel
或者xargs
如下:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
虽然parallel
已经涵盖了这一点,但xargs
如果目录名称包含空格,该方法将不起作用——您可以将其用作\0
行分隔符,或者简单地指示xargs
仅在换行符上拆分输入(如建议的那样马丁·邦纳) 反而:
xargs -0a<(<dirlist.txt tr \\{n,0} | cut -d/ -f1 -z) mkdir # \\{n,0} equals \\n \\0
xargs -d\\n -a<(<dirlist.txt cut -d/ -f1) mkdir
如果任何字段包含换行符,则需要识别“真正的”行尾,并仅用 替换那些换行符,例如\0
。那将是一个案例awk
,但我觉得在这里太牵强了。
答案2
您需要设置您的IFS='/'
for read
,然后将每个第一个字段分配到单独的变量中first
,将其余字段分配到变量中rest
,然后只对第一个字段的值进行操作(或者您可以read -ar array
对单个数组并使用"${array[0]}"
第一个字段的值。):
while IFS='/' read -r first rest;
do
echo mkdir -- "$first"
done < test.txt
###或者对于那些喜欢它的人来说,用单行表示:
<test.txt xargs -d'\n' -n1 sh -c 'echo mkdir -- "$'{1%%/*}'"' _
###或者一次性创建所有目录:
<test.txt xargs -d'\n' bash -c 'echo mkdir -- "$'{@%%/*}'"' _
这ANSI-C 引用$'...'
用于处理包含特殊字符的目录名。
请注意,_
末尾的(可以是任何字符或字符串)将是 argv[0],bash -c '...'
并且$@
将包含从 1 开始的其余参数;如果没有,在第二个命令中,第一个参数mkdir
将会丢失。
在${1%%/*}
使用shell(POSIX sh/bash/Korn/zsh)参数替换扩展,删除最长的斜杠匹配,后跟任何内容,直到传递给它的参数的末尾,这是一行参数;
附言:
- 删除
echo
前面的mkdir
以创建这些目录。 - 如果您的列表以 NUL 字符而不是 ewline 分隔,则替换
-d'\n'
为(假设您的目录名中嵌入了换行符)。-0
\n
答案3
内容test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
创建A[123]
文件夹的脚本:
file="test.txt"
while read -r line ; do
mkdir "${line%%/*}"
done < "$file"
输出ls
:
A 12"x4" dir
A1
A2
A3
答案4
使用 Perl:
perl -ne 'mkdir for /^(\w+)/' list.txt
或者
perl -ne 'mkdir for /^([^\/]+)/' list.txt
如果我们想接受目录名上的空格