List directories with spaces using Bash on linux
I would like to create a bash script to list all directories in a directory provided by the user via input, or all directories in the current directory (no input).
Here is what I have so far, but when I execute it I run into two problems.
1) the script completely ignores my input. The file is on my desktop, but when I type "home" as input, the script just prints out the desktop directories (current directory).
2) Directories are printed on their own lines (intended) but treat each word in the folder name as their own folder. those. is printed as:
this
folder
Here is the code I have so far:
#!/bin/bash
echo -n "Enter a directory to load files: "
read d
if [ $d="" ]; #if input is blank, assume d = current directory
then d=${PWD##*/}
for i in $(ls -d */);
do echo ${i%%/};
done
else #otherwise, print sub-directories of given directory
for i in $(ls -d */);
do echo ${i%%/};
done
fi
Also in your answer, please explain your answer as I am very new to bash.
Thanks for watching, I appreciate your time.
EDIT: Thanks to John1024's answer, I came up with the following:
#!/bin/bash
echo -n "Enter a directory to load files: "
IFS= read d
ls -1 -d "${d:-.}"/*/
And he does whatever I need. We really appreciate it!
source to share
I believe this script does what you want:
#!/bin/sh
ls -1 -d "${1:-.}"/*/
Usage example:
$ bash ./script.sh /usr/X11R6 /usr/X11R6/bin /usr/X11R6/man
Explanation:
-
-1
tells ls to print each file / directory on a separate line -
-d
According tols
a list of directories by name instead of their contents -
The shell
${1:-.}
will be the first argument to the script if there is one, or.
(which means the current directory) if it didn't.
Gain
The above script displays /
at the end of each directory name. If you don't want that, we can use sed
to remove trailing slashes from the output:
#!/bin/sh
ls -1d ${1:-.}/*/ | sed 's|/$||'
Revised version of your Script
Starting from your script, some simplifications can be made:
#!/bin/bash
echo -n "Enter a directory to load files: "
IFS= read d
d=${d:-$PWD}
for i in "$d"/*/
do
echo ${i%%/}
done
Notes:
-
IFS= read d
Usually the leading and trailing spaces are separated before the input is assigned
d
. However, if setIFS
to empty, space and space will be retained. So it will work even if the pathologically strange case is when the user specifies a directory whose name begins or ends with a space.If the user enters a backslash, the shell will try to treat it as an escape. If you don't like it, use
IFS= read -r d
and backslash will be treated as normal characters and not escape. -
d=${d:-$PWD}
If the user provided a value for
d
, this leaves it unchanged. If he didn't, it takes him over$PWD
. -
for i in "$d"/*/
This will span every subdirectory
$d
and will correctly handle subdirectory names with spaces, tabs, or any other odd character.In contrast, consider:
for i in $(ls -d */)
Once executed
ls
here, the shell will split the output into individual words. This is called "word splitting" and therefore this form of loop should be avoidedfor
.Note the double quotes in the
for i in "$d"/*/
. They are designed to prevent words from being split into$d
.
source to share