Create directories with a name from txt file which contain '/' character
![Creative The name of the picture](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO9GURib1T8z7lCwjOGLQaGtrueEthgQ8LO42ZX8cOfTqDK4jvDDpKkLFwf2J49kYCMNW7d4ABih_XCb_2UXdq5fPJDkoyg7-8g_YfRUot-XnaXkNYycsNp7lA5_TW9td0FFpLQ2APzKcZ/s1600/1.jpg)
![Creative The name of the picture](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYQ0N5W1qAOxLP7t7iOM6O6AzbZnkXUy16s7P_CWfOb5UbTQY_aDsc727chyphenhyphen5W4IppVNernMMQeaUFTB_rFzAd95_CDt-tnwN-nBx6JyUp2duGjPaL5-VgNO41AVsA_vu30EJcipdDG409/s400/Clash+Royale+CLAN+TAG%2523URR8PPP.png)
up vote
9
down vote
favorite
I have a .txt file that contains a text like this
A1/B1/C1
A2/B2/C2
A3/B3/C3
I want a script that reads the .txt file for each line then create a directory based on the first word (A1, A2, A3)
I have created script like this:
file="test.txt"
while IFS='' read -r line
do
name="line"
mkdir -p $line
done <"$file"
While I run it, it creates directory A1 then it also create sub-directories B1 and C1. the same happens for another line (A2* and A3*)
What should I do to create only A1, A2, A3 directories?
I don't want to make the name like A1/B1/C1 with '/' character in it.
I just want to take the word before '/' character and make it directory name.
Just "A1" "A2" "A3".
command-line bash directory text-processing
add a comment |Â
up vote
9
down vote
favorite
I have a .txt file that contains a text like this
A1/B1/C1
A2/B2/C2
A3/B3/C3
I want a script that reads the .txt file for each line then create a directory based on the first word (A1, A2, A3)
I have created script like this:
file="test.txt"
while IFS='' read -r line
do
name="line"
mkdir -p $line
done <"$file"
While I run it, it creates directory A1 then it also create sub-directories B1 and C1. the same happens for another line (A2* and A3*)
What should I do to create only A1, A2, A3 directories?
I don't want to make the name like A1/B1/C1 with '/' character in it.
I just want to take the word before '/' character and make it directory name.
Just "A1" "A2" "A3".
command-line bash directory text-processing
add a comment |Â
up vote
9
down vote
favorite
up vote
9
down vote
favorite
I have a .txt file that contains a text like this
A1/B1/C1
A2/B2/C2
A3/B3/C3
I want a script that reads the .txt file for each line then create a directory based on the first word (A1, A2, A3)
I have created script like this:
file="test.txt"
while IFS='' read -r line
do
name="line"
mkdir -p $line
done <"$file"
While I run it, it creates directory A1 then it also create sub-directories B1 and C1. the same happens for another line (A2* and A3*)
What should I do to create only A1, A2, A3 directories?
I don't want to make the name like A1/B1/C1 with '/' character in it.
I just want to take the word before '/' character and make it directory name.
Just "A1" "A2" "A3".
command-line bash directory text-processing
I have a .txt file that contains a text like this
A1/B1/C1
A2/B2/C2
A3/B3/C3
I want a script that reads the .txt file for each line then create a directory based on the first word (A1, A2, A3)
I have created script like this:
file="test.txt"
while IFS='' read -r line
do
name="line"
mkdir -p $line
done <"$file"
While I run it, it creates directory A1 then it also create sub-directories B1 and C1. the same happens for another line (A2* and A3*)
What should I do to create only A1, A2, A3 directories?
I don't want to make the name like A1/B1/C1 with '/' character in it.
I just want to take the word before '/' character and make it directory name.
Just "A1" "A2" "A3".
command-line bash directory text-processing
edited May 25 at 14:59
ñÃÂsýù÷
22.9k2191150
22.9k2191150
asked May 24 at 4:36
![](https://lh5.googleusercontent.com/-pc5X_QTuYTM/AAAAAAAAAAI/AAAAAAAAADU/C_VXpEMBbhE/photo.jpg?sz=32)
![](https://lh5.googleusercontent.com/-pc5X_QTuYTM/AAAAAAAAAAI/AAAAAAAAADU/C_VXpEMBbhE/photo.jpg?sz=32)
maulana
585
585
add a comment |Â
add a comment |Â
6 Answers
6
active
oldest
votes
up vote
13
down vote
accepted
You can just cut
the 1
st slash-d
elimited field of each line and give the list to mkdir
:
mkdir $(<dirlist.txt cut -d/ -f1)
Example run
$ 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
You may run into ARG_MAX problems if your list holds a huge number of directory names, in this case use GNU parallel
or
xargs
as follows:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
While parallel
has it covered, the xargs
approach wonâÂÂt work if the directory names contain spaces â you can either use as the line delimiter or simply instruct
xargs
to only split the input on newline characters (as proposed by Martin Bonner) instead:
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
In case any of the fields contains a newline character one would need to identify the âÂÂtrueâ line endings and replace only those newline characters with e.g. . That would be a case for
awk
, but I feel itâÂÂs too far fetched here.
Whyxargs -a<(....)
rather than<dirlist.txt cut -d/ -f1 | xargs
?
â Martin Bonner
May 24 at 16:25
1
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than mytr
approach â just realized thatparallel
has it covered by default.
â dessert
May 24 at 20:48
@MartinBonner Whyxargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)
â dessert
May 24 at 20:51
@AndreaCorbellini Oh, now I understand.<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.
â dessert
May 24 at 20:55
@MartinBonner More interestingly: Whycut <dirlist.txt
instead of justcut dirlist.txt
?
â dessert
May 24 at 21:06
 |Â
show 4 more comments
up vote
10
down vote
You need to set your IFS='/'
for read
and then assign each first field into separate variable first
and the rest of the fields into variable rest
and just work on first field's value (Or you can read -ar array
to a single array and use "$array[0]"
for the first field's value. ):
while IFS='/' read -r first rest;
do
echo mkdir "$first"
done < test.txt
Or in single line for those who like it:
<test.txt xargs -d'n' -n1 sh -c 'echo mkdir "$'1%%/*'"' _
Or create all directories in one-go:
<test.txt xargs -d'n' bash -c 'echo mkdir "$'@%%/*'"' _
The ANSI-C Quoting $'...'
is used to deal with directory names containing special characters.
Note that the _
(can be any character or string) at the end will be argv[0] to the bash -c '...'
and the $@
will contains rest of the parameters starting from 1; without that in second command the first parameter to the mkdir
will be lost.
In $1%%/*
using shell (POSIX sh/bash/Korn/zsh) parameter substitution expansion, removes longest possible match of a slash followed by anything till the end of the parameter passing into it which is a line that read by xargs;
P.s:
- Remove
echo
in front of themkdir
to create those directories. - Replace
-d'n'
with-0
if your list is separated with NUL characters instead of an
ewline (supposed there are newline in your directory name and of course there should not be a directory name with NUL characters either).
add a comment |Â
up vote
6
down vote
Contents of test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
Script to create A[123]
folders:
file="test.txt"
while read -r line ; do
mkdir "$line%%/*"
done < "$file"
Output of ls
:
A 12"x4" dir
A1
A2
A3
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
add a comment |Â
up vote
5
down vote
For simple case as shown in the question's input example, just use cut
and pass output to mkdir
via xargs
cut -f1 -d '/' file.txt | xargs -L1 mkdir
For handling cases where directory name may contain spaces, we could add -d 'n'
to the list of options:
$ 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
For more complex variations, such as A 12"x4" dir/B b/C c
as suggested by @OleTange in the comments, one may turn to awk
to create null-separated list instead of newline-separated list.
awk -F'/' 'printf "%s",$1' input.txt | xargs -0 mkdir
@dessert in the comments wondered whether printf
can be used instead of cut
, and technically speaking it can be used, for instance via limiting the printed string to the width of 3 characters only:
xargs -d 'n' printf "%.3sn" < input.txt | xargs -L1 mkdir
Not the cleanest way, but it proves printf
can be used. Of course, this gets problematic if directory name becomes longer than 3 characters.
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
add a comment |Â
up vote
2
down vote
using Perl:
perl -ne 'mkdir for /^(w+)/' list.txt
Or
perl -ne 'mkdir for /^([^/]+)/' list.txt
if we want to accept spaces on dir-names
1
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!
â dessert
May 24 at 21:03
add a comment |Â
up vote
0
down vote
GNU Parallel may be overkill for the task, but if you are going to do other stuff for each line, then it may be useful:
cat myfile.txt | parallel --colsep / mkdir 1
parallel -a myfile.txt --colsep / mkdir 1
It deals correctly with input like:
A 12"x4" dir/B b/C c
add a comment |Â
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
13
down vote
accepted
You can just cut
the 1
st slash-d
elimited field of each line and give the list to mkdir
:
mkdir $(<dirlist.txt cut -d/ -f1)
Example run
$ 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
You may run into ARG_MAX problems if your list holds a huge number of directory names, in this case use GNU parallel
or
xargs
as follows:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
While parallel
has it covered, the xargs
approach wonâÂÂt work if the directory names contain spaces â you can either use as the line delimiter or simply instruct
xargs
to only split the input on newline characters (as proposed by Martin Bonner) instead:
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
In case any of the fields contains a newline character one would need to identify the âÂÂtrueâ line endings and replace only those newline characters with e.g. . That would be a case for
awk
, but I feel itâÂÂs too far fetched here.
Whyxargs -a<(....)
rather than<dirlist.txt cut -d/ -f1 | xargs
?
â Martin Bonner
May 24 at 16:25
1
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than mytr
approach â just realized thatparallel
has it covered by default.
â dessert
May 24 at 20:48
@MartinBonner Whyxargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)
â dessert
May 24 at 20:51
@AndreaCorbellini Oh, now I understand.<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.
â dessert
May 24 at 20:55
@MartinBonner More interestingly: Whycut <dirlist.txt
instead of justcut dirlist.txt
?
â dessert
May 24 at 21:06
 |Â
show 4 more comments
up vote
13
down vote
accepted
You can just cut
the 1
st slash-d
elimited field of each line and give the list to mkdir
:
mkdir $(<dirlist.txt cut -d/ -f1)
Example run
$ 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
You may run into ARG_MAX problems if your list holds a huge number of directory names, in this case use GNU parallel
or
xargs
as follows:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
While parallel
has it covered, the xargs
approach wonâÂÂt work if the directory names contain spaces â you can either use as the line delimiter or simply instruct
xargs
to only split the input on newline characters (as proposed by Martin Bonner) instead:
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
In case any of the fields contains a newline character one would need to identify the âÂÂtrueâ line endings and replace only those newline characters with e.g. . That would be a case for
awk
, but I feel itâÂÂs too far fetched here.
Whyxargs -a<(....)
rather than<dirlist.txt cut -d/ -f1 | xargs
?
â Martin Bonner
May 24 at 16:25
1
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than mytr
approach â just realized thatparallel
has it covered by default.
â dessert
May 24 at 20:48
@MartinBonner Whyxargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)
â dessert
May 24 at 20:51
@AndreaCorbellini Oh, now I understand.<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.
â dessert
May 24 at 20:55
@MartinBonner More interestingly: Whycut <dirlist.txt
instead of justcut dirlist.txt
?
â dessert
May 24 at 21:06
 |Â
show 4 more comments
up vote
13
down vote
accepted
up vote
13
down vote
accepted
You can just cut
the 1
st slash-d
elimited field of each line and give the list to mkdir
:
mkdir $(<dirlist.txt cut -d/ -f1)
Example run
$ 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
You may run into ARG_MAX problems if your list holds a huge number of directory names, in this case use GNU parallel
or
xargs
as follows:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
While parallel
has it covered, the xargs
approach wonâÂÂt work if the directory names contain spaces â you can either use as the line delimiter or simply instruct
xargs
to only split the input on newline characters (as proposed by Martin Bonner) instead:
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
In case any of the fields contains a newline character one would need to identify the âÂÂtrueâ line endings and replace only those newline characters with e.g. . That would be a case for
awk
, but I feel itâÂÂs too far fetched here.
You can just cut
the 1
st slash-d
elimited field of each line and give the list to mkdir
:
mkdir $(<dirlist.txt cut -d/ -f1)
Example run
$ 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
You may run into ARG_MAX problems if your list holds a huge number of directory names, in this case use GNU parallel
or
xargs
as follows:
parallel mkdir :::: <(<dirlist.txt cut -d/ -f1)
xargs -a<(<dirlist.txt cut -d/ -f1) mkdir
While parallel
has it covered, the xargs
approach wonâÂÂt work if the directory names contain spaces â you can either use as the line delimiter or simply instruct
xargs
to only split the input on newline characters (as proposed by Martin Bonner) instead:
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
In case any of the fields contains a newline character one would need to identify the âÂÂtrueâ line endings and replace only those newline characters with e.g. . That would be a case for
awk
, but I feel itâÂÂs too far fetched here.
edited May 25 at 11:38
answered May 24 at 5:37
![](https://i.stack.imgur.com/9L8vd.png?s=32&g=1)
![](https://i.stack.imgur.com/9L8vd.png?s=32&g=1)
dessert
19.5k55594
19.5k55594
Whyxargs -a<(....)
rather than<dirlist.txt cut -d/ -f1 | xargs
?
â Martin Bonner
May 24 at 16:25
1
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than mytr
approach â just realized thatparallel
has it covered by default.
â dessert
May 24 at 20:48
@MartinBonner Whyxargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)
â dessert
May 24 at 20:51
@AndreaCorbellini Oh, now I understand.<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.
â dessert
May 24 at 20:55
@MartinBonner More interestingly: Whycut <dirlist.txt
instead of justcut dirlist.txt
?
â dessert
May 24 at 21:06
 |Â
show 4 more comments
Whyxargs -a<(....)
rather than<dirlist.txt cut -d/ -f1 | xargs
?
â Martin Bonner
May 24 at 16:25
1
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than mytr
approach â just realized thatparallel
has it covered by default.
â dessert
May 24 at 20:48
@MartinBonner Whyxargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)
â dessert
May 24 at 20:51
@AndreaCorbellini Oh, now I understand.<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.
â dessert
May 24 at 20:55
@MartinBonner More interestingly: Whycut <dirlist.txt
instead of justcut dirlist.txt
?
â dessert
May 24 at 21:06
Why
xargs -a<(....)
rather than <dirlist.txt cut -d/ -f1 | xargs
?â Martin Bonner
May 24 at 16:25
Why
xargs -a<(....)
rather than <dirlist.txt cut -d/ -f1 | xargs
?â Martin Bonner
May 24 at 16:25
1
1
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than my
tr
approach â just realized that parallel
has it covered by default.â dessert
May 24 at 20:48
@MartinBonner Thanks for clarifying, thatâÂÂs indeed simpler than my
tr
approach â just realized that parallel
has it covered by default.â dessert
May 24 at 20:48
@MartinBonner Why
xargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)â dessert
May 24 at 20:51
@MartinBonner Why
xargs -a<(....)
rather than a pipe â because I like it this way, as simple as that. :)â dessert
May 24 at 20:51
@AndreaCorbellini Oh, now I understand.
<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.â dessert
May 24 at 20:55
@AndreaCorbellini Oh, now I understand.
<(...)
helps with spaces as well, so itâÂÂs definitely the better choice â I donâÂÂt think anybody was using this file descriptor anyway.â dessert
May 24 at 20:55
@MartinBonner More interestingly: Why
cut <dirlist.txt
instead of just cut dirlist.txt
?â dessert
May 24 at 21:06
@MartinBonner More interestingly: Why
cut <dirlist.txt
instead of just cut dirlist.txt
?â dessert
May 24 at 21:06
 |Â
show 4 more comments
up vote
10
down vote
You need to set your IFS='/'
for read
and then assign each first field into separate variable first
and the rest of the fields into variable rest
and just work on first field's value (Or you can read -ar array
to a single array and use "$array[0]"
for the first field's value. ):
while IFS='/' read -r first rest;
do
echo mkdir "$first"
done < test.txt
Or in single line for those who like it:
<test.txt xargs -d'n' -n1 sh -c 'echo mkdir "$'1%%/*'"' _
Or create all directories in one-go:
<test.txt xargs -d'n' bash -c 'echo mkdir "$'@%%/*'"' _
The ANSI-C Quoting $'...'
is used to deal with directory names containing special characters.
Note that the _
(can be any character or string) at the end will be argv[0] to the bash -c '...'
and the $@
will contains rest of the parameters starting from 1; without that in second command the first parameter to the mkdir
will be lost.
In $1%%/*
using shell (POSIX sh/bash/Korn/zsh) parameter substitution expansion, removes longest possible match of a slash followed by anything till the end of the parameter passing into it which is a line that read by xargs;
P.s:
- Remove
echo
in front of themkdir
to create those directories. - Replace
-d'n'
with-0
if your list is separated with NUL characters instead of an
ewline (supposed there are newline in your directory name and of course there should not be a directory name with NUL characters either).
add a comment |Â
up vote
10
down vote
You need to set your IFS='/'
for read
and then assign each first field into separate variable first
and the rest of the fields into variable rest
and just work on first field's value (Or you can read -ar array
to a single array and use "$array[0]"
for the first field's value. ):
while IFS='/' read -r first rest;
do
echo mkdir "$first"
done < test.txt
Or in single line for those who like it:
<test.txt xargs -d'n' -n1 sh -c 'echo mkdir "$'1%%/*'"' _
Or create all directories in one-go:
<test.txt xargs -d'n' bash -c 'echo mkdir "$'@%%/*'"' _
The ANSI-C Quoting $'...'
is used to deal with directory names containing special characters.
Note that the _
(can be any character or string) at the end will be argv[0] to the bash -c '...'
and the $@
will contains rest of the parameters starting from 1; without that in second command the first parameter to the mkdir
will be lost.
In $1%%/*
using shell (POSIX sh/bash/Korn/zsh) parameter substitution expansion, removes longest possible match of a slash followed by anything till the end of the parameter passing into it which is a line that read by xargs;
P.s:
- Remove
echo
in front of themkdir
to create those directories. - Replace
-d'n'
with-0
if your list is separated with NUL characters instead of an
ewline (supposed there are newline in your directory name and of course there should not be a directory name with NUL characters either).
add a comment |Â
up vote
10
down vote
up vote
10
down vote
You need to set your IFS='/'
for read
and then assign each first field into separate variable first
and the rest of the fields into variable rest
and just work on first field's value (Or you can read -ar array
to a single array and use "$array[0]"
for the first field's value. ):
while IFS='/' read -r first rest;
do
echo mkdir "$first"
done < test.txt
Or in single line for those who like it:
<test.txt xargs -d'n' -n1 sh -c 'echo mkdir "$'1%%/*'"' _
Or create all directories in one-go:
<test.txt xargs -d'n' bash -c 'echo mkdir "$'@%%/*'"' _
The ANSI-C Quoting $'...'
is used to deal with directory names containing special characters.
Note that the _
(can be any character or string) at the end will be argv[0] to the bash -c '...'
and the $@
will contains rest of the parameters starting from 1; without that in second command the first parameter to the mkdir
will be lost.
In $1%%/*
using shell (POSIX sh/bash/Korn/zsh) parameter substitution expansion, removes longest possible match of a slash followed by anything till the end of the parameter passing into it which is a line that read by xargs;
P.s:
- Remove
echo
in front of themkdir
to create those directories. - Replace
-d'n'
with-0
if your list is separated with NUL characters instead of an
ewline (supposed there are newline in your directory name and of course there should not be a directory name with NUL characters either).
You need to set your IFS='/'
for read
and then assign each first field into separate variable first
and the rest of the fields into variable rest
and just work on first field's value (Or you can read -ar array
to a single array and use "$array[0]"
for the first field's value. ):
while IFS='/' read -r first rest;
do
echo mkdir "$first"
done < test.txt
Or in single line for those who like it:
<test.txt xargs -d'n' -n1 sh -c 'echo mkdir "$'1%%/*'"' _
Or create all directories in one-go:
<test.txt xargs -d'n' bash -c 'echo mkdir "$'@%%/*'"' _
The ANSI-C Quoting $'...'
is used to deal with directory names containing special characters.
Note that the _
(can be any character or string) at the end will be argv[0] to the bash -c '...'
and the $@
will contains rest of the parameters starting from 1; without that in second command the first parameter to the mkdir
will be lost.
In $1%%/*
using shell (POSIX sh/bash/Korn/zsh) parameter substitution expansion, removes longest possible match of a slash followed by anything till the end of the parameter passing into it which is a line that read by xargs;
P.s:
- Remove
echo
in front of themkdir
to create those directories. - Replace
-d'n'
with-0
if your list is separated with NUL characters instead of an
ewline (supposed there are newline in your directory name and of course there should not be a directory name with NUL characters either).
edited Jun 5 at 2:57
answered May 24 at 4:54
ñÃÂsýù÷
22.9k2191150
22.9k2191150
add a comment |Â
add a comment |Â
up vote
6
down vote
Contents of test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
Script to create A[123]
folders:
file="test.txt"
while read -r line ; do
mkdir "$line%%/*"
done < "$file"
Output of ls
:
A 12"x4" dir
A1
A2
A3
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
add a comment |Â
up vote
6
down vote
Contents of test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
Script to create A[123]
folders:
file="test.txt"
while read -r line ; do
mkdir "$line%%/*"
done < "$file"
Output of ls
:
A 12"x4" dir
A1
A2
A3
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
add a comment |Â
up vote
6
down vote
up vote
6
down vote
Contents of test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
Script to create A[123]
folders:
file="test.txt"
while read -r line ; do
mkdir "$line%%/*"
done < "$file"
Output of ls
:
A 12"x4" dir
A1
A2
A3
Contents of test.txt
:
A 12"x4" dir/B b/C c
A1/B1/C1
A2/B2/C2
A3/B3/C3
Script to create A[123]
folders:
file="test.txt"
while read -r line ; do
mkdir "$line%%/*"
done < "$file"
Output of ls
:
A 12"x4" dir
A1
A2
A3
edited May 25 at 11:55
answered May 24 at 4:55
xiota
1,0461421
1,0461421
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
add a comment |Â
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
How do you deal with input like:
A 12"x4" dir/B b/C c
?â Ole Tange
May 25 at 11:32
How do you deal with input like:
A 12"x4" dir/B b/C c
?â Ole Tange
May 25 at 11:32
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
Ole Tange - That comment seems completely out of scope for the question.
â DocSalvager
May 31 at 4:13
add a comment |Â
up vote
5
down vote
For simple case as shown in the question's input example, just use cut
and pass output to mkdir
via xargs
cut -f1 -d '/' file.txt | xargs -L1 mkdir
For handling cases where directory name may contain spaces, we could add -d 'n'
to the list of options:
$ 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
For more complex variations, such as A 12"x4" dir/B b/C c
as suggested by @OleTange in the comments, one may turn to awk
to create null-separated list instead of newline-separated list.
awk -F'/' 'printf "%s",$1' input.txt | xargs -0 mkdir
@dessert in the comments wondered whether printf
can be used instead of cut
, and technically speaking it can be used, for instance via limiting the printed string to the width of 3 characters only:
xargs -d 'n' printf "%.3sn" < input.txt | xargs -L1 mkdir
Not the cleanest way, but it proves printf
can be used. Of course, this gets problematic if directory name becomes longer than 3 characters.
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
add a comment |Â
up vote
5
down vote
For simple case as shown in the question's input example, just use cut
and pass output to mkdir
via xargs
cut -f1 -d '/' file.txt | xargs -L1 mkdir
For handling cases where directory name may contain spaces, we could add -d 'n'
to the list of options:
$ 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
For more complex variations, such as A 12"x4" dir/B b/C c
as suggested by @OleTange in the comments, one may turn to awk
to create null-separated list instead of newline-separated list.
awk -F'/' 'printf "%s",$1' input.txt | xargs -0 mkdir
@dessert in the comments wondered whether printf
can be used instead of cut
, and technically speaking it can be used, for instance via limiting the printed string to the width of 3 characters only:
xargs -d 'n' printf "%.3sn" < input.txt | xargs -L1 mkdir
Not the cleanest way, but it proves printf
can be used. Of course, this gets problematic if directory name becomes longer than 3 characters.
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
add a comment |Â
up vote
5
down vote
up vote
5
down vote
For simple case as shown in the question's input example, just use cut
and pass output to mkdir
via xargs
cut -f1 -d '/' file.txt | xargs -L1 mkdir
For handling cases where directory name may contain spaces, we could add -d 'n'
to the list of options:
$ 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
For more complex variations, such as A 12"x4" dir/B b/C c
as suggested by @OleTange in the comments, one may turn to awk
to create null-separated list instead of newline-separated list.
awk -F'/' 'printf "%s",$1' input.txt | xargs -0 mkdir
@dessert in the comments wondered whether printf
can be used instead of cut
, and technically speaking it can be used, for instance via limiting the printed string to the width of 3 characters only:
xargs -d 'n' printf "%.3sn" < input.txt | xargs -L1 mkdir
Not the cleanest way, but it proves printf
can be used. Of course, this gets problematic if directory name becomes longer than 3 characters.
For simple case as shown in the question's input example, just use cut
and pass output to mkdir
via xargs
cut -f1 -d '/' file.txt | xargs -L1 mkdir
For handling cases where directory name may contain spaces, we could add -d 'n'
to the list of options:
$ 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
For more complex variations, such as A 12"x4" dir/B b/C c
as suggested by @OleTange in the comments, one may turn to awk
to create null-separated list instead of newline-separated list.
awk -F'/' 'printf "%s",$1' input.txt | xargs -0 mkdir
@dessert in the comments wondered whether printf
can be used instead of cut
, and technically speaking it can be used, for instance via limiting the printed string to the width of 3 characters only:
xargs -d 'n' printf "%.3sn" < input.txt | xargs -L1 mkdir
Not the cleanest way, but it proves printf
can be used. Of course, this gets problematic if directory name becomes longer than 3 characters.
edited May 25 at 14:54
answered May 24 at 5:32
![](https://i.stack.imgur.com/U1Jy6.jpg?s=32&g=1)
![](https://i.stack.imgur.com/U1Jy6.jpg?s=32&g=1)
Sergiy Kolodyazhnyy
64k9127274
64k9127274
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
add a comment |Â
How do you deal with input like:A 12"x4" dir/B b/C c
?
â Ole Tange
May 25 at 11:32
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
How do you deal with input like:
A 12"x4" dir/B b/C c
?â Ole Tange
May 25 at 11:32
How do you deal with input like:
A 12"x4" dir/B b/C c
?â Ole Tange
May 25 at 11:32
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
@OleTange See the edit.
â Sergiy Kolodyazhnyy
May 25 at 14:54
add a comment |Â
up vote
2
down vote
using Perl:
perl -ne 'mkdir for /^(w+)/' list.txt
Or
perl -ne 'mkdir for /^([^/]+)/' list.txt
if we want to accept spaces on dir-names
1
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!
â dessert
May 24 at 21:03
add a comment |Â
up vote
2
down vote
using Perl:
perl -ne 'mkdir for /^(w+)/' list.txt
Or
perl -ne 'mkdir for /^([^/]+)/' list.txt
if we want to accept spaces on dir-names
1
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!
â dessert
May 24 at 21:03
add a comment |Â
up vote
2
down vote
up vote
2
down vote
using Perl:
perl -ne 'mkdir for /^(w+)/' list.txt
Or
perl -ne 'mkdir for /^([^/]+)/' list.txt
if we want to accept spaces on dir-names
using Perl:
perl -ne 'mkdir for /^(w+)/' list.txt
Or
perl -ne 'mkdir for /^([^/]+)/' list.txt
if we want to accept spaces on dir-names
edited May 25 at 12:27
ñÃÂsýù÷
22.9k2191150
22.9k2191150
answered May 24 at 19:06
JJoao
1,24059
1,24059
1
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!
â dessert
May 24 at 21:03
add a comment |Â
1
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!
â dessert
May 24 at 21:03
1
1
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!â dessert
May 24 at 21:03
perl -ne 'mkdir for /^([^/]+)/' list.txt
to cover spaces in dir names. I finally need to learn Perl â thank you!â dessert
May 24 at 21:03
add a comment |Â
up vote
0
down vote
GNU Parallel may be overkill for the task, but if you are going to do other stuff for each line, then it may be useful:
cat myfile.txt | parallel --colsep / mkdir 1
parallel -a myfile.txt --colsep / mkdir 1
It deals correctly with input like:
A 12"x4" dir/B b/C c
add a comment |Â
up vote
0
down vote
GNU Parallel may be overkill for the task, but if you are going to do other stuff for each line, then it may be useful:
cat myfile.txt | parallel --colsep / mkdir 1
parallel -a myfile.txt --colsep / mkdir 1
It deals correctly with input like:
A 12"x4" dir/B b/C c
add a comment |Â
up vote
0
down vote
up vote
0
down vote
GNU Parallel may be overkill for the task, but if you are going to do other stuff for each line, then it may be useful:
cat myfile.txt | parallel --colsep / mkdir 1
parallel -a myfile.txt --colsep / mkdir 1
It deals correctly with input like:
A 12"x4" dir/B b/C c
GNU Parallel may be overkill for the task, but if you are going to do other stuff for each line, then it may be useful:
cat myfile.txt | parallel --colsep / mkdir 1
parallel -a myfile.txt --colsep / mkdir 1
It deals correctly with input like:
A 12"x4" dir/B b/C c
edited May 25 at 11:44
answered May 25 at 11:26
Ole Tange
9711719
9711719
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1039649%2fcreate-directories-with-a-name-from-txt-file-which-contain-character%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password