-2

My script:

#!/bin/sh

_directory1="/home/user/test1"
_directory2="test2"

cd "${_directory1}/$_directory2"

for i in *
do
    echo "$i"
done

And here is the error:

./myscript.sh: 6: cd: can't cd to /home/user/test1/test2

What am I doing wrong?

Chris Davies
  • 116,213
  • 16
  • 160
  • 287

1 Answers1

3

Your original code before edits:

#!/bin/sh

_directory1="~/test1"
_directory2="test2"

for i in $(cd "${_directory1}/$_directory2")
do
    echo "$i"
done
  1. The tilde (~) does not behave like a variable. It will, for example, not expand to the path to your home directory when used within quotes. In a script, use $HOME instead of tilde. ~ is a "shortcut" that you may want to use on the command line, but $HOME is more descriptive in a script.

  2. cd does not output anything that you can loop over, so using cd in a command substitution with for will not do you anything good. Unfortunately, it's unclear what you want your loop to actually do, so I can't give you a surefire alternative implementation.


The code with your edits:

#!/bin/sh

_directory1="/home/user/test1"
_directory2="test2"

cd "${_directory1}/$_directory2"

for i in *
do
    echo "$i"
done

This code would only output

"./myscript.sh: 6: cd: can't cd to /test2"

if you misspell the name of the variable _directory1 (and the misspelled variable is empty, and the /test2 directory does not exist).


You then edited the error message again to say that it outputs

./myscript.sh: 6: cd: can't cd to /home/user/test1/test2

which simply means that the directory /home/user/test1/test2 does not exist. You have not given evidence that this directory does exist so we have to take your system's word for that.


Here's a script that lists the contents of a directory (assuming that the directory exists). The code prints the full pathname of each file.

#!/bin/bash

topdir=$HOME/test1
subdir=test2

printf '%s\n' "$topdir/$subdir"/*

Or,

#!/bin/bash

topdir=$HOME/test1
subdir=test2

shopt -s nullglob

for name in "$topdir/$subdir"/*; do
    printf '%s\n' "$name"
done

The nullglob shell option makes the loop not run at all if the given pattern does not match anything. Without setting the nullglob option, the pattern would remain unexpanded if if didn't match anything, and the loop would use it as the value for $name in a single iteration.

You may also want to set the dotglob shell option (shopt -s dotglob) if you are interested in hidden names (filenames starting with a . character).

Or, without printing the full path to each filename,

#!/bin/bash

topdir=$HOME/test1
subdir=test2

cd "$topdir/$subdir" || exit 1

printf '%s\n' *

The exit 1 will terminate the script if the cd fails.

Or,

#!/bin/bash

topdir=$HOME/test1
subdir=test2

cd "$topdir/$subdir" || exit 1

shopt -s nullglob

for name in *; do
    printf '%s\n' "$name"
done

To print only the filenames without their full path, without using cd:

#!/bin/bash

topdir=$HOME/test1
subdir=test2

shopt -s nullglob

for name in "$topdir/$subdir"/*; do
    printf '%s\n' "$( basename "$name" )"

    # or:  printf '%s\n' "${name##*/}"

done

This uses the basename utility to extract only the filename portion of the pathnames. The alternative in the comment uses a standard parameter substitution, ${name##*/}, to delete the initial directory path before the filenames (literally "remove the longest prefix string matching the pattern */ from $name").

Kusalananda
  • 333,661
  • I understand., didn't know that. But this is not the problem. When I made this like your saying, I got the same result. I edited now. –  Mar 09 '20 at 21:34
  • I just want to cd a specific directory. Then do a for loop to see what's inside. –  Mar 09 '20 at 21:35
  • @AhmetMehmet That's not the error I get with the code that is currently in the question. Please double check your actual code for typos of the _directory1 variable's name. – Kusalananda Mar 09 '20 at 21:35
  • I just edited my code and still got that error. –  Mar 09 '20 at 21:40
  • Strangely the script is working now. Is there a way that for do the job without cd? –  Mar 09 '20 at 21:51