mau*_*ana 8 command-line bash directory text-processing
我有一个 .txt 文件,其中包含这样的文本
A1/B1/C1
A2/B2/C2
A3/B3/C3
Run Code Online (Sandbox Code Playgroud)
我想要一个脚本来读取每一行的 .txt 文件,然后根据第一个单词(A1、A2、A3)创建一个目录
我已经创建了这样的脚本:
file="test.txt"
while IFS='' read -r line
do
name="line"
mkdir -p $line
done <"$file"
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它会创建目录 A1,然后还会创建子目录 B1 和 C1。另一行(A2* 和 A3*)也会发生同样的情况
我应该怎么做才能只创建 A1、A2、A3 目录?
我不想让名字像 A1/B1/C1 那样带有 '/' 字符。我只想在 '/' 字符之前取这个词并将其设为目录名。只是“A1”“A2”“A3”。
des*_*ert 14
您可以只cut
使用每行的1
st 斜杠d
分隔字段并将列表提供给mkdir
:
mkdir $(<dirlist.txt cut -d/ -f1)
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
如果您的列表包含大量目录名称,您可能会遇到ARG_MAX问题,在这种情况下使用 GNUparallel
或
xargs
如下:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
Run Code Online (Sandbox Code Playgroud)
虽然parallel
涵盖了它,但xargs
如果目录名称包含空格,则该方法将不起作用 - 您可以将其\0
用作行分隔符,也可以简单地指示xargs
仅将输入拆分为换行符(由Martin Bonner提出):
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
Run Code Online (Sandbox Code Playgroud)
如果任何字段包含换行符,则需要识别“真正的”行尾,并仅将这些换行符替换为例如\0
. 这将是 的情况awk
,但我觉得这里太牵强了。
αғs*_*нιη 12
您需要设置IFS='/'
forread
然后将每个第一个字段分配给单独的变量first
,将其余字段分配给变量,rest
然后只处理第一个字段的值(或者您可以read -ar array
使用单个数组并"${array[0]}"
用于第一个字段的值。):
while IFS='/' read -r first rest;
do
echo mkdir -- "$first"
done < test.txt
Run Code Online (Sandbox Code Playgroud)
###Or 对于喜欢它的人来说,单行:
<test.txt xargs -d'\n' -n1 sh -c 'echo mkdir -- "$'{1%%/*}'"' _
Run Code Online (Sandbox Code Playgroud)
###或一次性创建所有目录:
<test.txt xargs -d'\n' bash -c 'echo mkdir -- "$'{@%%/*}'"' _
Run Code Online (Sandbox Code Playgroud)
在ANSI-C报价$'...'
是用来处理包含特殊字符的目录名称。
请注意,_
末尾的(可以是任何字符或字符串)将是 argv[0] 到 thebash -c '...'
并且该$@
will 包含从 1 开始的其余参数;如果没有在第二个命令中,第一个参数mkdir
将丢失。
在${1%%/*}
使用shell (POSIX sh/bash/Korn/zsh) 参数替换扩展时,删除斜杠后跟任何内容的最长可能匹配,直到传递给它的参数结束,这是由xargs读取的一行;
附:
echo
前面的mkdir
以创建那些目录。-d'\n'
用-0
,如果你的列表与NULL字符,而不是分开的\n
ewline(应该有你的目录名/嵌入换行符)。内容test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
Run Code Online (Sandbox Code Playgroud)
创建A[123]
文件夹的脚本:
file="test.txt"
while read -r line ; do
mkdir "${line%%/*}"
done < "$file"
Run Code Online (Sandbox Code Playgroud)
的输出ls
:
A 12"x4" dir
A1
A2
A3
Run Code Online (Sandbox Code Playgroud)
对于问题输入示例中所示的简单情况,只需使用cut
并将输出传递给mkdir
viaxargs
cut -f1 -d '/' file.txt | xargs -L1 mkdir
Run Code Online (Sandbox Code Playgroud)
对于处理目录名称可能包含空格的情况,我们可以添加-d '\n'
到选项列表中:
$ cat input.txt
A 1/B 1/C 1
A 2/B 2/C 2
A 3/B 2/C 2
$ cut -f1 -d '/' input.txt | xargs -d '\n' mkdir
$ ls
A 1 A 2 A 3 input.txt
Run Code Online (Sandbox Code Playgroud)
对于更复杂的变体,例如A 12"x4" dir/B b/C c
@OleTange 在评论中所建议的,可以转向awk
创建空分隔列表而不是换行分隔列表。
awk -F'/' '{printf "%s\0",$1}' input.txt | xargs -0 mkdir
Run Code Online (Sandbox Code Playgroud)
评论中的@dessert 想知道是否printf
可以使用 代替cut
,从技术上讲可以使用它,例如通过将打印的字符串限制为仅 3 个字符的宽度:
xargs -d '\n' printf "%.3s\n" < input.txt | xargs -L1 mkdir
Run Code Online (Sandbox Code Playgroud)
不是最干净的方式,但它证明printf
可以使用。当然,如果目录名称变得超过 3 个字符,这就会出现问题。
归档时间: |
|
查看次数: |
5685 次 |
最近记录: |