for loop in folders with n character in their names
![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 some folders with n
character it their names.
for example:
$ ls
''$'n''Test'
Thats refer to a folder with Test name and a empty line before its name.
So when I run some scripts like this, in its parent directory:
while IFS= read -r d; do
rmdir $d
done < <(find * -type d)
It shows:
rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory
Because it runs twice, once on n
and the another on Test
, because the folder name has two lines.
So how can I solve this issue such that, script knows nTest
is just one folder?
command-line bash scripts
 |Â
show 7 more comments
up vote
9
down vote
favorite
I have some folders with n
character it their names.
for example:
$ ls
''$'n''Test'
Thats refer to a folder with Test name and a empty line before its name.
So when I run some scripts like this, in its parent directory:
while IFS= read -r d; do
rmdir $d
done < <(find * -type d)
It shows:
rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory
Because it runs twice, once on n
and the another on Test
, because the folder name has two lines.
So how can I solve this issue such that, script knows nTest
is just one folder?
command-line bash scripts
3
You need to use find's-print0
directive, and the-d
read option. See stackoverflow.com/a/40189667/7552
â glenn jackman
Jun 4 at 22:27
1
@glennjackman Please answer!
â dessert
Jun 4 at 22:27
@glennjackman Thanks for your reply butfind * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
command have this outputrmdir: failed to remove 'Test': No such file or directory
.
â Tara S Volpe
Jun 4 at 22:34
5
You must quote the variable :rmdir "$file"
â glenn jackman
Jun 4 at 22:40
1
@glennjackman Just post this as answer. It's a proper solution and besides comments are not the best place for that. Upvote already implied :)
â Sergiy Kolodyazhnyy
Jun 5 at 0:56
 |Â
show 7 more comments
up vote
9
down vote
favorite
up vote
9
down vote
favorite
I have some folders with n
character it their names.
for example:
$ ls
''$'n''Test'
Thats refer to a folder with Test name and a empty line before its name.
So when I run some scripts like this, in its parent directory:
while IFS= read -r d; do
rmdir $d
done < <(find * -type d)
It shows:
rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory
Because it runs twice, once on n
and the another on Test
, because the folder name has two lines.
So how can I solve this issue such that, script knows nTest
is just one folder?
command-line bash scripts
I have some folders with n
character it their names.
for example:
$ ls
''$'n''Test'
Thats refer to a folder with Test name and a empty line before its name.
So when I run some scripts like this, in its parent directory:
while IFS= read -r d; do
rmdir $d
done < <(find * -type d)
It shows:
rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory
Because it runs twice, once on n
and the another on Test
, because the folder name has two lines.
So how can I solve this issue such that, script knows nTest
is just one folder?
command-line bash scripts
asked Jun 4 at 22:21
Tara S Volpe
18017
18017
3
You need to use find's-print0
directive, and the-d
read option. See stackoverflow.com/a/40189667/7552
â glenn jackman
Jun 4 at 22:27
1
@glennjackman Please answer!
â dessert
Jun 4 at 22:27
@glennjackman Thanks for your reply butfind * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
command have this outputrmdir: failed to remove 'Test': No such file or directory
.
â Tara S Volpe
Jun 4 at 22:34
5
You must quote the variable :rmdir "$file"
â glenn jackman
Jun 4 at 22:40
1
@glennjackman Just post this as answer. It's a proper solution and besides comments are not the best place for that. Upvote already implied :)
â Sergiy Kolodyazhnyy
Jun 5 at 0:56
 |Â
show 7 more comments
3
You need to use find's-print0
directive, and the-d
read option. See stackoverflow.com/a/40189667/7552
â glenn jackman
Jun 4 at 22:27
1
@glennjackman Please answer!
â dessert
Jun 4 at 22:27
@glennjackman Thanks for your reply butfind * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
command have this outputrmdir: failed to remove 'Test': No such file or directory
.
â Tara S Volpe
Jun 4 at 22:34
5
You must quote the variable :rmdir "$file"
â glenn jackman
Jun 4 at 22:40
1
@glennjackman Just post this as answer. It's a proper solution and besides comments are not the best place for that. Upvote already implied :)
â Sergiy Kolodyazhnyy
Jun 5 at 0:56
3
3
You need to use find's
-print0
directive, and the -d
read option. See stackoverflow.com/a/40189667/7552â glenn jackman
Jun 4 at 22:27
You need to use find's
-print0
directive, and the -d
read option. See stackoverflow.com/a/40189667/7552â glenn jackman
Jun 4 at 22:27
1
1
@glennjackman Please answer!
â dessert
Jun 4 at 22:27
@glennjackman Please answer!
â dessert
Jun 4 at 22:27
@glennjackman Thanks for your reply but
find * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
command have this output rmdir: failed to remove 'Test': No such file or directory
.â Tara S Volpe
Jun 4 at 22:34
@glennjackman Thanks for your reply but
find * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
command have this output rmdir: failed to remove 'Test': No such file or directory
.â Tara S Volpe
Jun 4 at 22:34
5
5
You must quote the variable :
rmdir "$file"
â glenn jackman
Jun 4 at 22:40
You must quote the variable :
rmdir "$file"
â glenn jackman
Jun 4 at 22:40
1
1
@glennjackman Just post this as answer. It's a proper solution and besides comments are not the best place for that. Upvote already implied :)
â Sergiy Kolodyazhnyy
Jun 5 at 0:56
@glennjackman Just post this as answer. It's a proper solution and besides comments are not the best place for that. Upvote already implied :)
â Sergiy Kolodyazhnyy
Jun 5 at 0:56
 |Â
show 7 more comments
3 Answers
3
active
oldest
votes
up vote
12
down vote
accepted
You've only single command there, so it's sufficient to call find
with -exec
flag calling rmdir
:
find -depth -type d -exec rmdir ;
Or use the -delete
option as in find -type d -delete
, but it won't work with non-empty directories. For that you will also need -empty
flag. Note also, -delete
implies -depth
so that may be skipped. Thus another viable alternative that keeps everything as one process:
find -type d -empty -delete
If the directory not empty, use rm -rf ;
. To isolate only directories with n
in filename we can combine bash's ANSI-C quoting $'...'
with -name
opption:
find -type d -name $'*n*' -empty -delete
POSIX-ly, we could handle it this way:
find -depth -type d -name "$(printf '*n*' )" -exec rmdir ;
It is worth mentioning that if your goal is removal of directories, then -delete
is sufficient, however if you want to execute a command on directory then -exec
is most appropriate.
See also
- How to delete directories based on
find
output? - find -delete does not delete non-empty directories
2
⦠userm -rf
with care. ;P DoesnâÂÂtfind
have a-delete
option btw? It deletes empty directories and throws errors for non-empty ones likermdir
â might be less expensive.
â dessert
Jun 4 at 22:41
3
@dessert It does and I added that in, but-delete
won't remove non-empty directories. Hence, the careful use ofrm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
6
Always dry-run suchfind
commands without any destructive payload (i.e. remove the-delete
or-exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...
â Byte Commander
Jun 4 at 22:50
2
This is askubuntu.com so we can assume GNUfind
. Use-exec rmdir +
to batch multiple args onto onermdir
command line. And BTW "but it won't work with non-empty directories." applies tormdir
as well, so that's not actually a difference from-delete
. It's a difference fromrm -r
.
â Peter Cordes
Jun 5 at 1:01
2
find -type d -empty -delete
(-delete
implies-depth
).
â Kevin
Jun 5 at 2:51
 |Â
show 7 more comments
up vote
10
down vote
You could use shell globs instead of find
:
for d in */ ; do
rmdir "$d"
done
The shell glob */
matches all folders in the current directory. This for-loop construction takes care of correct word splitting automatically.
Note that depending on your shell options, this might ignore hidden folders (name starting with a .). That behaviour can be changed to match all files for the current session using the command shopt -s dotglob
.
Also don't forget to always quote your variables.
the glob will only find files/directories in the current directory, not recursively likefind
does
â ilkkachu
Jun 5 at 9:54
1
You are right @ilkkachu. That could be changed by enabling the globstar shell optionshopt -s globstar
and using a**/*/
glob instead.
â Byte Commander
Jun 5 at 10:26
add a comment |Â
up vote
6
down vote
Both answers written so far call rmdir
once per directory, but as rmdir
can take multiple arguments I wonder: IsnâÂÂt there a more efficient way?
One could simply do
rmdir */
and thatâÂÂs definitely the easiest and most efficient way, but it may throw an error in the case of many directories (see What is the maximum length of command line arguments in gnome-terminal?). If you want this approach to work recursively, enable the globstar
shell option with shopt -s globstar
and use **/*/
instead of */
.
With GNU find
(and if we donâÂÂt just want to use -delete
), we could do
find -depth -type d -exec rmdir +
which builts the command line âÂÂin much the same way that xargs
builds its command linesâ (man find
). Substitute -depth
for -maxdepth 1
if you donâÂÂt want it to work recursively.
A third and IMO brilliant way is explained by steeldriver in this answer:
printf '%s' */ | xargs -0 rmdir
This uses the shell builtin printf
to build a zero-delimited argument list, this list is then piped to xargs
which calls rmdir
exactly as often as necessary. You can make it work recursively with shopt -s globstar
and **/*/
instead of */
as above.
2
find
is recursive, but the OP's loop isn't. To replicate that behaviour, usefind -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick withprintf
to emulatefind -print0
, I hadn't seen that before.
â Peter Cordes
Jun 5 at 9:08
1
Oh! I saw thels
and thewhile
loop, I missed that they were redirecting from a process substitution withfind
instead of pipingls
into the loop and just not showing it for some reason. Thatfind *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use*/
.find .
would be much better, becausefind
is faster atstat
ing than bash's glob expansion.
â Peter Cordes
Jun 5 at 9:15
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
12
down vote
accepted
You've only single command there, so it's sufficient to call find
with -exec
flag calling rmdir
:
find -depth -type d -exec rmdir ;
Or use the -delete
option as in find -type d -delete
, but it won't work with non-empty directories. For that you will also need -empty
flag. Note also, -delete
implies -depth
so that may be skipped. Thus another viable alternative that keeps everything as one process:
find -type d -empty -delete
If the directory not empty, use rm -rf ;
. To isolate only directories with n
in filename we can combine bash's ANSI-C quoting $'...'
with -name
opption:
find -type d -name $'*n*' -empty -delete
POSIX-ly, we could handle it this way:
find -depth -type d -name "$(printf '*n*' )" -exec rmdir ;
It is worth mentioning that if your goal is removal of directories, then -delete
is sufficient, however if you want to execute a command on directory then -exec
is most appropriate.
See also
- How to delete directories based on
find
output? - find -delete does not delete non-empty directories
2
⦠userm -rf
with care. ;P DoesnâÂÂtfind
have a-delete
option btw? It deletes empty directories and throws errors for non-empty ones likermdir
â might be less expensive.
â dessert
Jun 4 at 22:41
3
@dessert It does and I added that in, but-delete
won't remove non-empty directories. Hence, the careful use ofrm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
6
Always dry-run suchfind
commands without any destructive payload (i.e. remove the-delete
or-exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...
â Byte Commander
Jun 4 at 22:50
2
This is askubuntu.com so we can assume GNUfind
. Use-exec rmdir +
to batch multiple args onto onermdir
command line. And BTW "but it won't work with non-empty directories." applies tormdir
as well, so that's not actually a difference from-delete
. It's a difference fromrm -r
.
â Peter Cordes
Jun 5 at 1:01
2
find -type d -empty -delete
(-delete
implies-depth
).
â Kevin
Jun 5 at 2:51
 |Â
show 7 more comments
up vote
12
down vote
accepted
You've only single command there, so it's sufficient to call find
with -exec
flag calling rmdir
:
find -depth -type d -exec rmdir ;
Or use the -delete
option as in find -type d -delete
, but it won't work with non-empty directories. For that you will also need -empty
flag. Note also, -delete
implies -depth
so that may be skipped. Thus another viable alternative that keeps everything as one process:
find -type d -empty -delete
If the directory not empty, use rm -rf ;
. To isolate only directories with n
in filename we can combine bash's ANSI-C quoting $'...'
with -name
opption:
find -type d -name $'*n*' -empty -delete
POSIX-ly, we could handle it this way:
find -depth -type d -name "$(printf '*n*' )" -exec rmdir ;
It is worth mentioning that if your goal is removal of directories, then -delete
is sufficient, however if you want to execute a command on directory then -exec
is most appropriate.
See also
- How to delete directories based on
find
output? - find -delete does not delete non-empty directories
2
⦠userm -rf
with care. ;P DoesnâÂÂtfind
have a-delete
option btw? It deletes empty directories and throws errors for non-empty ones likermdir
â might be less expensive.
â dessert
Jun 4 at 22:41
3
@dessert It does and I added that in, but-delete
won't remove non-empty directories. Hence, the careful use ofrm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
6
Always dry-run suchfind
commands without any destructive payload (i.e. remove the-delete
or-exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...
â Byte Commander
Jun 4 at 22:50
2
This is askubuntu.com so we can assume GNUfind
. Use-exec rmdir +
to batch multiple args onto onermdir
command line. And BTW "but it won't work with non-empty directories." applies tormdir
as well, so that's not actually a difference from-delete
. It's a difference fromrm -r
.
â Peter Cordes
Jun 5 at 1:01
2
find -type d -empty -delete
(-delete
implies-depth
).
â Kevin
Jun 5 at 2:51
 |Â
show 7 more comments
up vote
12
down vote
accepted
up vote
12
down vote
accepted
You've only single command there, so it's sufficient to call find
with -exec
flag calling rmdir
:
find -depth -type d -exec rmdir ;
Or use the -delete
option as in find -type d -delete
, but it won't work with non-empty directories. For that you will also need -empty
flag. Note also, -delete
implies -depth
so that may be skipped. Thus another viable alternative that keeps everything as one process:
find -type d -empty -delete
If the directory not empty, use rm -rf ;
. To isolate only directories with n
in filename we can combine bash's ANSI-C quoting $'...'
with -name
opption:
find -type d -name $'*n*' -empty -delete
POSIX-ly, we could handle it this way:
find -depth -type d -name "$(printf '*n*' )" -exec rmdir ;
It is worth mentioning that if your goal is removal of directories, then -delete
is sufficient, however if you want to execute a command on directory then -exec
is most appropriate.
See also
- How to delete directories based on
find
output? - find -delete does not delete non-empty directories
You've only single command there, so it's sufficient to call find
with -exec
flag calling rmdir
:
find -depth -type d -exec rmdir ;
Or use the -delete
option as in find -type d -delete
, but it won't work with non-empty directories. For that you will also need -empty
flag. Note also, -delete
implies -depth
so that may be skipped. Thus another viable alternative that keeps everything as one process:
find -type d -empty -delete
If the directory not empty, use rm -rf ;
. To isolate only directories with n
in filename we can combine bash's ANSI-C quoting $'...'
with -name
opption:
find -type d -name $'*n*' -empty -delete
POSIX-ly, we could handle it this way:
find -depth -type d -name "$(printf '*n*' )" -exec rmdir ;
It is worth mentioning that if your goal is removal of directories, then -delete
is sufficient, however if you want to execute a command on directory then -exec
is most appropriate.
See also
- How to delete directories based on
find
output? - find -delete does not delete non-empty directories
edited Jun 5 at 17:49
answered Jun 4 at 22:40
![](https://i.stack.imgur.com/U1Jy6.jpg?s=32&g=1)
![](https://i.stack.imgur.com/U1Jy6.jpg?s=32&g=1)
Sergiy Kolodyazhnyy
63.8k9127273
63.8k9127273
2
⦠userm -rf
with care. ;P DoesnâÂÂtfind
have a-delete
option btw? It deletes empty directories and throws errors for non-empty ones likermdir
â might be less expensive.
â dessert
Jun 4 at 22:41
3
@dessert It does and I added that in, but-delete
won't remove non-empty directories. Hence, the careful use ofrm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
6
Always dry-run suchfind
commands without any destructive payload (i.e. remove the-delete
or-exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...
â Byte Commander
Jun 4 at 22:50
2
This is askubuntu.com so we can assume GNUfind
. Use-exec rmdir +
to batch multiple args onto onermdir
command line. And BTW "but it won't work with non-empty directories." applies tormdir
as well, so that's not actually a difference from-delete
. It's a difference fromrm -r
.
â Peter Cordes
Jun 5 at 1:01
2
find -type d -empty -delete
(-delete
implies-depth
).
â Kevin
Jun 5 at 2:51
 |Â
show 7 more comments
2
⦠userm -rf
with care. ;P DoesnâÂÂtfind
have a-delete
option btw? It deletes empty directories and throws errors for non-empty ones likermdir
â might be less expensive.
â dessert
Jun 4 at 22:41
3
@dessert It does and I added that in, but-delete
won't remove non-empty directories. Hence, the careful use ofrm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
6
Always dry-run suchfind
commands without any destructive payload (i.e. remove the-delete
or-exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...
â Byte Commander
Jun 4 at 22:50
2
This is askubuntu.com so we can assume GNUfind
. Use-exec rmdir +
to batch multiple args onto onermdir
command line. And BTW "but it won't work with non-empty directories." applies tormdir
as well, so that's not actually a difference from-delete
. It's a difference fromrm -r
.
â Peter Cordes
Jun 5 at 1:01
2
find -type d -empty -delete
(-delete
implies-depth
).
â Kevin
Jun 5 at 2:51
2
2
⦠use
rm -rf
with care. ;P DoesnâÂÂt find
have a -delete
option btw? It deletes empty directories and throws errors for non-empty ones like rmdir
â might be less expensive.â dessert
Jun 4 at 22:41
⦠use
rm -rf
with care. ;P DoesnâÂÂt find
have a -delete
option btw? It deletes empty directories and throws errors for non-empty ones like rmdir
â might be less expensive.â dessert
Jun 4 at 22:41
3
3
@dessert It does and I added that in, but
-delete
won't remove non-empty directories. Hence, the careful use of rm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
@dessert It does and I added that in, but
-delete
won't remove non-empty directories. Hence, the careful use of rm -rf
â Sergiy Kolodyazhnyy
Jun 4 at 22:47
6
6
Always dry-run such
find
commands without any destructive payload (i.e. remove the -delete
or -exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...â Byte Commander
Jun 4 at 22:50
Always dry-run such
find
commands without any destructive payload (i.e. remove the -delete
or -exec whatever ;
) to check if the list of affected files is actually correct and does not contain stuff that should not get deleted...â Byte Commander
Jun 4 at 22:50
2
2
This is askubuntu.com so we can assume GNU
find
. Use -exec rmdir +
to batch multiple args onto one rmdir
command line. And BTW "but it won't work with non-empty directories." applies to rmdir
as well, so that's not actually a difference from -delete
. It's a difference from rm -r
.â Peter Cordes
Jun 5 at 1:01
This is askubuntu.com so we can assume GNU
find
. Use -exec rmdir +
to batch multiple args onto one rmdir
command line. And BTW "but it won't work with non-empty directories." applies to rmdir
as well, so that's not actually a difference from -delete
. It's a difference from rm -r
.â Peter Cordes
Jun 5 at 1:01
2
2
find -type d -empty -delete
(-delete
implies -depth
).â Kevin
Jun 5 at 2:51
find -type d -empty -delete
(-delete
implies -depth
).â Kevin
Jun 5 at 2:51
 |Â
show 7 more comments
up vote
10
down vote
You could use shell globs instead of find
:
for d in */ ; do
rmdir "$d"
done
The shell glob */
matches all folders in the current directory. This for-loop construction takes care of correct word splitting automatically.
Note that depending on your shell options, this might ignore hidden folders (name starting with a .). That behaviour can be changed to match all files for the current session using the command shopt -s dotglob
.
Also don't forget to always quote your variables.
the glob will only find files/directories in the current directory, not recursively likefind
does
â ilkkachu
Jun 5 at 9:54
1
You are right @ilkkachu. That could be changed by enabling the globstar shell optionshopt -s globstar
and using a**/*/
glob instead.
â Byte Commander
Jun 5 at 10:26
add a comment |Â
up vote
10
down vote
You could use shell globs instead of find
:
for d in */ ; do
rmdir "$d"
done
The shell glob */
matches all folders in the current directory. This for-loop construction takes care of correct word splitting automatically.
Note that depending on your shell options, this might ignore hidden folders (name starting with a .). That behaviour can be changed to match all files for the current session using the command shopt -s dotglob
.
Also don't forget to always quote your variables.
the glob will only find files/directories in the current directory, not recursively likefind
does
â ilkkachu
Jun 5 at 9:54
1
You are right @ilkkachu. That could be changed by enabling the globstar shell optionshopt -s globstar
and using a**/*/
glob instead.
â Byte Commander
Jun 5 at 10:26
add a comment |Â
up vote
10
down vote
up vote
10
down vote
You could use shell globs instead of find
:
for d in */ ; do
rmdir "$d"
done
The shell glob */
matches all folders in the current directory. This for-loop construction takes care of correct word splitting automatically.
Note that depending on your shell options, this might ignore hidden folders (name starting with a .). That behaviour can be changed to match all files for the current session using the command shopt -s dotglob
.
Also don't forget to always quote your variables.
You could use shell globs instead of find
:
for d in */ ; do
rmdir "$d"
done
The shell glob */
matches all folders in the current directory. This for-loop construction takes care of correct word splitting automatically.
Note that depending on your shell options, this might ignore hidden folders (name starting with a .). That behaviour can be changed to match all files for the current session using the command shopt -s dotglob
.
Also don't forget to always quote your variables.
answered Jun 4 at 22:36
![](https://i.stack.imgur.com/m8DYH.jpg?s=32&g=1)
![](https://i.stack.imgur.com/m8DYH.jpg?s=32&g=1)
Byte Commander
58k26155263
58k26155263
the glob will only find files/directories in the current directory, not recursively likefind
does
â ilkkachu
Jun 5 at 9:54
1
You are right @ilkkachu. That could be changed by enabling the globstar shell optionshopt -s globstar
and using a**/*/
glob instead.
â Byte Commander
Jun 5 at 10:26
add a comment |Â
the glob will only find files/directories in the current directory, not recursively likefind
does
â ilkkachu
Jun 5 at 9:54
1
You are right @ilkkachu. That could be changed by enabling the globstar shell optionshopt -s globstar
and using a**/*/
glob instead.
â Byte Commander
Jun 5 at 10:26
the glob will only find files/directories in the current directory, not recursively like
find
doesâ ilkkachu
Jun 5 at 9:54
the glob will only find files/directories in the current directory, not recursively like
find
doesâ ilkkachu
Jun 5 at 9:54
1
1
You are right @ilkkachu. That could be changed by enabling the globstar shell option
shopt -s globstar
and using a **/*/
glob instead.â Byte Commander
Jun 5 at 10:26
You are right @ilkkachu. That could be changed by enabling the globstar shell option
shopt -s globstar
and using a **/*/
glob instead.â Byte Commander
Jun 5 at 10:26
add a comment |Â
up vote
6
down vote
Both answers written so far call rmdir
once per directory, but as rmdir
can take multiple arguments I wonder: IsnâÂÂt there a more efficient way?
One could simply do
rmdir */
and thatâÂÂs definitely the easiest and most efficient way, but it may throw an error in the case of many directories (see What is the maximum length of command line arguments in gnome-terminal?). If you want this approach to work recursively, enable the globstar
shell option with shopt -s globstar
and use **/*/
instead of */
.
With GNU find
(and if we donâÂÂt just want to use -delete
), we could do
find -depth -type d -exec rmdir +
which builts the command line âÂÂin much the same way that xargs
builds its command linesâ (man find
). Substitute -depth
for -maxdepth 1
if you donâÂÂt want it to work recursively.
A third and IMO brilliant way is explained by steeldriver in this answer:
printf '%s' */ | xargs -0 rmdir
This uses the shell builtin printf
to build a zero-delimited argument list, this list is then piped to xargs
which calls rmdir
exactly as often as necessary. You can make it work recursively with shopt -s globstar
and **/*/
instead of */
as above.
2
find
is recursive, but the OP's loop isn't. To replicate that behaviour, usefind -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick withprintf
to emulatefind -print0
, I hadn't seen that before.
â Peter Cordes
Jun 5 at 9:08
1
Oh! I saw thels
and thewhile
loop, I missed that they were redirecting from a process substitution withfind
instead of pipingls
into the loop and just not showing it for some reason. Thatfind *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use*/
.find .
would be much better, becausefind
is faster atstat
ing than bash's glob expansion.
â Peter Cordes
Jun 5 at 9:15
add a comment |Â
up vote
6
down vote
Both answers written so far call rmdir
once per directory, but as rmdir
can take multiple arguments I wonder: IsnâÂÂt there a more efficient way?
One could simply do
rmdir */
and thatâÂÂs definitely the easiest and most efficient way, but it may throw an error in the case of many directories (see What is the maximum length of command line arguments in gnome-terminal?). If you want this approach to work recursively, enable the globstar
shell option with shopt -s globstar
and use **/*/
instead of */
.
With GNU find
(and if we donâÂÂt just want to use -delete
), we could do
find -depth -type d -exec rmdir +
which builts the command line âÂÂin much the same way that xargs
builds its command linesâ (man find
). Substitute -depth
for -maxdepth 1
if you donâÂÂt want it to work recursively.
A third and IMO brilliant way is explained by steeldriver in this answer:
printf '%s' */ | xargs -0 rmdir
This uses the shell builtin printf
to build a zero-delimited argument list, this list is then piped to xargs
which calls rmdir
exactly as often as necessary. You can make it work recursively with shopt -s globstar
and **/*/
instead of */
as above.
2
find
is recursive, but the OP's loop isn't. To replicate that behaviour, usefind -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick withprintf
to emulatefind -print0
, I hadn't seen that before.
â Peter Cordes
Jun 5 at 9:08
1
Oh! I saw thels
and thewhile
loop, I missed that they were redirecting from a process substitution withfind
instead of pipingls
into the loop and just not showing it for some reason. Thatfind *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use*/
.find .
would be much better, becausefind
is faster atstat
ing than bash's glob expansion.
â Peter Cordes
Jun 5 at 9:15
add a comment |Â
up vote
6
down vote
up vote
6
down vote
Both answers written so far call rmdir
once per directory, but as rmdir
can take multiple arguments I wonder: IsnâÂÂt there a more efficient way?
One could simply do
rmdir */
and thatâÂÂs definitely the easiest and most efficient way, but it may throw an error in the case of many directories (see What is the maximum length of command line arguments in gnome-terminal?). If you want this approach to work recursively, enable the globstar
shell option with shopt -s globstar
and use **/*/
instead of */
.
With GNU find
(and if we donâÂÂt just want to use -delete
), we could do
find -depth -type d -exec rmdir +
which builts the command line âÂÂin much the same way that xargs
builds its command linesâ (man find
). Substitute -depth
for -maxdepth 1
if you donâÂÂt want it to work recursively.
A third and IMO brilliant way is explained by steeldriver in this answer:
printf '%s' */ | xargs -0 rmdir
This uses the shell builtin printf
to build a zero-delimited argument list, this list is then piped to xargs
which calls rmdir
exactly as often as necessary. You can make it work recursively with shopt -s globstar
and **/*/
instead of */
as above.
Both answers written so far call rmdir
once per directory, but as rmdir
can take multiple arguments I wonder: IsnâÂÂt there a more efficient way?
One could simply do
rmdir */
and thatâÂÂs definitely the easiest and most efficient way, but it may throw an error in the case of many directories (see What is the maximum length of command line arguments in gnome-terminal?). If you want this approach to work recursively, enable the globstar
shell option with shopt -s globstar
and use **/*/
instead of */
.
With GNU find
(and if we donâÂÂt just want to use -delete
), we could do
find -depth -type d -exec rmdir +
which builts the command line âÂÂin much the same way that xargs
builds its command linesâ (man find
). Substitute -depth
for -maxdepth 1
if you donâÂÂt want it to work recursively.
A third and IMO brilliant way is explained by steeldriver in this answer:
printf '%s' */ | xargs -0 rmdir
This uses the shell builtin printf
to build a zero-delimited argument list, this list is then piped to xargs
which calls rmdir
exactly as often as necessary. You can make it work recursively with shopt -s globstar
and **/*/
instead of */
as above.
edited Jun 6 at 22:09
answered Jun 5 at 8:33
![](https://i.stack.imgur.com/9L8vd.png?s=32&g=1)
![](https://i.stack.imgur.com/9L8vd.png?s=32&g=1)
dessert
19.4k55494
19.4k55494
2
find
is recursive, but the OP's loop isn't. To replicate that behaviour, usefind -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick withprintf
to emulatefind -print0
, I hadn't seen that before.
â Peter Cordes
Jun 5 at 9:08
1
Oh! I saw thels
and thewhile
loop, I missed that they were redirecting from a process substitution withfind
instead of pipingls
into the loop and just not showing it for some reason. Thatfind *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use*/
.find .
would be much better, becausefind
is faster atstat
ing than bash's glob expansion.
â Peter Cordes
Jun 5 at 9:15
add a comment |Â
2
find
is recursive, but the OP's loop isn't. To replicate that behaviour, usefind -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick withprintf
to emulatefind -print0
, I hadn't seen that before.
â Peter Cordes
Jun 5 at 9:08
1
Oh! I saw thels
and thewhile
loop, I missed that they were redirecting from a process substitution withfind
instead of pipingls
into the loop and just not showing it for some reason. Thatfind *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use*/
.find .
would be much better, becausefind
is faster atstat
ing than bash's glob expansion.
â Peter Cordes
Jun 5 at 9:15
2
2
find
is recursive, but the OP's loop isn't. To replicate that behaviour, use find -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick with printf
to emulate find -print0
, I hadn't seen that before.â Peter Cordes
Jun 5 at 9:08
find
is recursive, but the OP's loop isn't. To replicate that behaviour, use find -maxdepth 1 -type d -exec rmdir +
. (-depth
is redundant in that case.) Neat trick with printf
to emulate find -print0
, I hadn't seen that before.â Peter Cordes
Jun 5 at 9:08
1
1
Oh! I saw the
ls
and the while
loop, I missed that they were redirecting from a process substitution with find
instead of piping ls
into the loop and just not showing it for some reason. That find *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use */
. find .
would be much better, because find
is faster at stat
ing than bash's glob expansion.â Peter Cordes
Jun 5 at 9:15
Oh! I saw the
ls
and the while
loop, I missed that they were redirecting from a process substitution with find
instead of piping ls
into the loop and just not showing it for some reason. That find *
is really buried. Yes it's recursive, and will fail if there are too many directory entries in the directory, including non-directories because it doesn't use */
. find .
would be much better, because find
is faster at stat
ing than bash's glob expansion.â Peter Cordes
Jun 5 at 9:15
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%2f1043640%2ffor-loop-in-folders-with-n-character-in-their-names%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
3
You need to use find's
-print0
directive, and the-d
read option. See stackoverflow.com/a/40189667/7552â glenn jackman
Jun 4 at 22:27
1
@glennjackman Please answer!
â dessert
Jun 4 at 22:27
@glennjackman Thanks for your reply but
find * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
command have this outputrmdir: failed to remove 'Test': No such file or directory
.â Tara S Volpe
Jun 4 at 22:34
5
You must quote the variable :
rmdir "$file"
â glenn jackman
Jun 4 at 22:40
1
@glennjackman Just post this as answer. It's a proper solution and besides comments are not the best place for that. Upvote already implied :)
â Sergiy Kolodyazhnyy
Jun 5 at 0:56