BASH SHELL: How to list contents of a directory that contains sub dirs that have a spaces in the sub-dir name and these sub dirs then contain a sub dir with a special character for a name

I have a directory that contains sub-directories where the sub directory names all contain spaces and each further sub dir contains a sub dir with that is actually called @. How do you pass that as a variable in a script. I'd like to do it this way    for dir in ls /opt/app; do ls /opt/app/'${dir}'/'@'; done but this doesn't work and not sure what to do to get it to work.

                App Dir 1 App Dir 2 App Dir 3 App Dir 4 AppDir 5
                            @          @         @              @              @

On the command line if I want to list the contents of these dirs I have put single quotes around the Sub Dir Name in order to escape the special character since the name contains spaces but this is such a poor way to do it because I don't want to have to list the sub dirs by name but do it more the way i tried above.
ls /opt/app/'App Dir 1'/'@'/ ; ls /opt/app/'App Dir 2'/'@' ; ls /opt/app/'App Dir 3'/'@' ; ......

I'd like to do it this way
for dir in ls /opt/app; do ls /opt/app/'${dir}'/'@'; done  but not sure who to get this way to work
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

David FavorLinux/LXD/WordPress/Hosting SavantCommented:
Depends on what you're doing with the output.

One of these simple commands will suffice...

ls -R
find . -type f

Open in new window

Then apply grep to filter as required.

Sometimes it's just easier to do a find + grep than deal with odd characters.
-type f is a match for  regular file
-type d is a directory
find path -type d -name  '* *' -depth 2

I based on what you are looking for would use perl to iterate through ....

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Harisha M GEngineerCommented:
Try this:

for i in opt/app/*/@ ; do ls "$i" ; done

Open in new window

nociSoftware EngineerCommented:
How about:

find /opt/apps -type f -print0 | xargs -0 ls -l 

Open in new window

The -print0 on find and the -0 on xargs work in tandem. -print0 sees to it that each file & path name is terminated with a nul-character ('\0')
xargs -0 accepts nul-terminated strings and handles each as an argument to the program mentioned after it....
xargs also collects as much names as could fit in the commandline to call the next command with a lot of single arguments.

another way can be:
find /opt/apps -type f -print0 | xargs -n 1 -0 command-that-can-handle-only-one-file-name

Open in new window

Here some differences are shown:
find /opt/apps -type f -print0 | xargs -n 1 -0 echo      # only one arg per command
find /opt/apps -type f -print0 | xargs -n 2 -0 echo      # 2 files / command
find /opt/apps -type f -print0 | xargs -n 5 -0 echo      # 5 files per command

Open in new window

lolaferrariAuthor Commented:
Thanks very much for all your input. all of it was helpful
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.