1

I would want to iterate over contents of a directory and list only ordinary files. The path of the directory is given as an user input. The script works if the input is current directory but not with others. I am aware that this can be done using ls.. but i need to use a for .. in control structure.

#!/bin/bash
echo "Enter the path:"

read path

contents=$(ls $path)

for content in $contents
do
   if [ -f $content ];
   then
       echo $content
   fi
done
Abhay Hegde
  • 321
  • 2
  • 12

4 Answers4

0

ls is only returning the file names, not including the path. You need to either:

  1. Change your working directory to the path in question, or
  2. Combine the path with the names for your -f test

Option #2 would just change:

    if [ -f $content ];

to:

    if [ -f "$path/$content" ];

Note that there are other issues here; ls may make changes to the output that break this, depending on wrapping. If you insist on using ls, you can at least make it (somewhat) safer with:

contents="$(command ls -1F "$path")"
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
0

You have two ways of doing this properly:

Either loop through the * pattern and test file type:

#!/usr/bin/env bash

echo "Enter the path:"

read -r path

for file in "$path/"*; do
  if [ -f "$file" ]; then
    echo "$file"
  fi
done

Or using find to iterate a null delimited list of file-names:

#!/usr/bin/env bash

echo "Enter the path:"

read -r path

while IFS= read -r -d '' file; do
  echo "$file"
done < <(
  find "$path" -maxdepth 1 -type f -print0
)

The second way is preferred since it will properly handle files with special characters and offload the file-type check to the find command.

Léa Gris
  • 17,497
  • 4
  • 32
  • 41
0

Use file, set to search for files (-type f) from $path directory:

   find "$path" -type f
suspectus
  • 16,548
  • 8
  • 49
  • 57
0

Here is what you could write:

#!/usr/bin/env bash

path=
while [[ ! $path ]]; do
    read -p "Enter path: " path
done

for file in "$path"/*; do
    [[ -f $file ]] && printf '%s\n' "$file"
done

If you want to traverse all the subdirectories recursively looking for files, you can use globstar:

shopt -s globstar
for file in "$path"/**; do
    printf '%s\n' "$file"
done

In case you are looking for specific files based on one or more patterns or some other condition, you could use the find command to pick those files. See this post:

How to loop through file names returned by find?

Related

codeforester
  • 39,467
  • 16
  • 112
  • 140