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!

+3


source to share


1 answer


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 to ls

    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 set IFS

    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 avoided for

    .

    Note the double quotes in the for i in "$d"/*/

    . They are designed to prevent words from being split into $d

    .

+3


source







All Articles