16

I have a folder named 'sample' and it has 3 files in it. I want to write a shell script which will read these files inside the sample folder and post it to an HTTP site using curl.

I have written the following for listing files inside the folder:

for dir in sample/*; do
        echo $dir;
        done

But it gives me the following output:

sample/log

sample/clk

sample/demo

It is attaching the parent folder in it. I want the output as follows (without the parent folder name)

log

clk

demo

How do I do this?

1
  • 1
    use 'cd' first. If you need 'curl' it, you still need enter the directory. Also you can use echo ${dir##*/} to take off the path. Commented Apr 6, 2017 at 15:41

4 Answers 4

41

Use basename to strip the leading path off of the files:

for file in sample/*; do
    echo "$(basename "$file")"
done

Though why not:

( cd sample; ls )
5

Assuming your shell supports it you could use parameter expansion

for path in sample/*; do
    printf -- '%s\n' "${path##*/}"
done

or you could just change to that directory and do the listing there

2
  • 1
    The -- is not needed here. The first argument is a fixed string with no dashes. Commented May 29, 2018 at 10:21
  • Also, ${parameter##pattern} is supported by all POSIX shells. Commented Jun 19, 2018 at 13:22
5

It depends what you want to do with the directories.

To simply print the name, without a check whether it is a directory you could use ls:

ls -1 sample

Better would be find, because you can use filters:

find sample -type d -maxdepth 1 -printf '%f\n'

If you want to run commands on the files, you should use find and not a for loop:

find sample -type d -maxdepth 1 -exec basename {} \;
1
  • Yes. Just to clarify. ls sample/* will show sample/log, etc. ls sample will show only log. Commented Sep 10, 2020 at 15:37
4

Because *nix systems allow nearly any character to be part of a filename (including including whitespace, newlines, commas, pipe symbols, etc.), you should never parse the output of the "ls" command in a shell script. It's not reliable. See Why you shouldn't parse the output of ls.

Use "find" to create a list of files. If you are using Bash, you can insert the output of "find" into an array. Example below, with the caveat that I used a non-working "curl" command!

searchDir="sample/"
oldFiles=()
while IFS= read -r -d $'\0' foundFile; do
    oldFiles+=("$foundFile")
done < <(find "$searchDir" -maxdepth 1 -type f -print0 2> /dev/null)

if [[ ${#oldFiles[@]} -ne 0 ]]; then
    for file in "${oldFiles[@]}"; do
        curl -F ‘data=@"$file"’ UPLOAD_ADDRESS
    done
fi
3
  • What is the directory here? $'\0' ? I want to pass a directory that's in a variable... Commented Nov 19, 2018 at 17:30
  • searchDir is the directory variable. "-d $'\0'" sets the delimiter of the read command to null. Commented Nov 27, 2018 at 2:59
  • How do I achieve the same thing in a sh shell? I am using #!/bin/sh Commented Jul 3, 2019 at 3:10

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.