0

I am using the following code :

#!/bin/bash
for f in $1 ; do
        echo $f
done 

The aim is to list down all the files in the directory that is passed as an argument to this script. But it's not printing anything. Not sure what could be wrong with this.
dnaiel
  • 407
  • 7
  • 13
  • 2
    Just do `ls "$1"`. Or maybe `ls "${1-.}"` – William Pursell Mar 02 '22 at 19:35
  • `for f in $1` is only going to look at the first parameter. Perhaps you meant `for f in $*`. – Tim Roberts Mar 02 '22 at 19:44
  • If the code is put in a file called `myprog` and it is run with `bash myprog x` then it should output `x`. It does that for me. It's not printing what you want, but its not "not printing anything". If it's not printing anything for you, either you are running different code or there is something wrong with how you are running it. – pjh Mar 02 '22 at 22:51
  • I've just added a pretty thoroguh answer at the location of the duplicate question here: [How to get the list of files in a directory in a shell script?](https://stackoverflow.com/a/71345102/4561887) – Gabriel Staples Mar 03 '22 at 23:49

2 Answers2

1

If you only need to list files not directories. (this part is unclear to me.) find is your friend.

find $1 -depth 1 -type file

Returns:

./output.tf
./locals.tf
./main.tf
./.tflint.hcl
./versions.tf
./.pre-commit-config.yaml
./makefile
./.terraformignore
./jenkins.tf
./devops.tf
./README.md
./.gitignore
./variables.tf
./Jenkinsfile
./accounts.tf
./.terraform.lock.hcl

Furthermore, please run man find.

Josh Beauregard
  • 2,498
  • 2
  • 20
  • 37
  • The further plan was to print only the directory names excluding symbolic links to directories – dnaiel Mar 02 '22 at 19:29
  • 1
    Is `-type fle` a typo? – Gabriel Staples Mar 02 '22 at 19:35
  • @dnaiel then you definitely want to look at `man find` It's got all the filters you need – Josh Beauregard Mar 02 '22 at 19:36
  • @GabrielStaples that it is thanks! – Josh Beauregard Mar 02 '22 at 19:36
  • I think `-depth 1` is a typo too. `-depth` takes no options. I think you mean `-maxdepth 1` – Gabriel Staples Mar 02 '22 at 19:40
  • 1
    Make sure to run your command before leaving it as an answer, and copy-paste the cmd you actually ran into your answer to avoid typos. – Gabriel Staples Mar 02 '22 at 19:42
  • 1
    `$1` should be quoted (`"$1"`). Use [Shellcheck](https://www.shellcheck.net/) to find bugs like this. Even with quoting, the command may fail, or (worse) silently do the wrong thing, if `$1` begins with a hyphen (which is unusual for paths, but it does happen). One way to avoid the problem is to use `"${1/#-/./-}"` instead of `"$1"`. That will replace a path like `-abc` with `./-abc` but leave paths like `abc` or `/abc` unchanged. – pjh Mar 02 '22 at 22:19
  • 1
    Are people actually running this? I suspect people are upvoting it just because it _looks right_ not because it _is right_. Running `find . -depth 1 -type file` as a quick test which follows the pattern in this answer results in an error: `find: paths must precede expression: \`1'`. – Gabriel Staples Mar 03 '22 at 15:03
  • 1
    This answer seems to me to be totally non-functional. It seems to me the _correct_ answer is: `find "$1" -maxdepth 1 -type f`. Running `find . -maxdepth 1 -type f` as a quick test actually works for me. – Gabriel Staples Mar 03 '22 at 15:10
  • @GabrielStaples unfortunate `find` is one of those core apps that have been bastardized across distros, so the flags on a mac vs a linux distro can vary – Josh Beauregard Mar 14 '22 at 15:46
  • @JoshBeauregard, ahhh. I see. If you update your `find` line with one example for Mac and one for Linux, and add a comment above each to indicate which system it is for, I'll upvote your answer. I've been very confused, trying to run your example. – Gabriel Staples Mar 14 '22 at 19:50
1

Try this Shellcheck-clean pure Bash code for the "further plan" mentioned in a comment:

#! /bin/bash -p

# List all subdirectories of the directory given in the first positional
# parameter.  Include subdirectories whose names begin with dot.  Exclude
# symlinks to directories.

shopt -s dotglob
shopt -s nullglob
for d in "$1"/*/; do
    dir=${d%/}                  # Remove trailing slash
    [[ -L $dir ]] && continue   # Skip symlinks
    printf '%s\n' "$dir"
done
  • shopt -s dotglob causes shell glob patterns to match names that begin with a dot (.). (find does this by default.)
  • shopt -s nullglob causes shell glob patterns to expand to nothing when nothing matches, so looping over glob patterns is safe.
  • The trailing slash on the glob pattern ("$1"/*/) causes only directories (including symlinks to directories) to be matched. It's removed (dir=${d%/}) partly for cleanliness but mostly to enable the test for a symlink ([[ -L $dir ]]) to work.
  • See the accepted, and excellent, answer to Why is printf better than echo? for an explanation of why I used printf instead of echo to print the subdirectory paths.
pjh
  • 6,388
  • 2
  • 16
  • 17