0

My final goal for this script is to:

  1. Visit folder in loop
  2. find the descriptor.mod
  3. Rename it to its folder name
  4. Relocate it to a specific folder
  5. repeat

Currently, when I am trying to visit the folder I get this error

$ . a.sh
bash: cd: 'a.sh/': No such file or directory
haha
bash: cd: 'Folder 1/': No such file or directory
haha
bash: cd: 'Folder 2/': No such file or directory
haha
bash: cd: 'Folder 3/': No such file or directory
haha
bash: cd: 'Folder 4/': No such file or directory
haha
bash: cd: 'Folder 5/': No such file or directory
haha
bash: cd: 'Folder 6/': No such file or directory
haha

This is my code. There are six folders named Folder {number}

for f in *
do
    cd "'$f/'"
    echo "haha"
    cd ..
done

cd "E:\School\LINUX"

EDIT: Found it. I changed for f in * to for f in */

1 Answers1

4

The command cd "'$f/'" contains outer double-quotes that will be removed by the shell after they serve they purpose of quoting. The inner single-quotes will survive and get to cd as parts of the argument. (More about quotes within quotes here: Parameter expansion (variable expansion) and quotes within quotes.)

In effect you're trying to cd to e.g. 'Folder 1/' with literal single-quotes, while the existing target is Folder 1/. There is no 'Folder 1/' directory.


Additionally * matches non-directories as well. a.sh is the script. After you add / and single-quotes, you're trying to cd to 'a.sh/'. There is no such directory.

Having failed to cd into this non-directoriy, you then subsequently also run cd .., which will take you out of the starting directory, and into its parent. From here, the entities that the original * matched are no longer visible, and so all further attempts to cd fail too... in fact, each subsequent failed cd will take you up one directory.


You need for f in */ to iterate over directories only (but note * doesn't match dotfiles). Then you don't need to add / because the trailing slash appears from the expansion of $f (although another trailing slash shouldn't break anything). And you absolutely shouldn't add single-quotes to the argument of cd. The relevant line should be cd "$f".


You could use a loop like the following to iterate through all entities, skipping non-directories, and handling cd errors correctly:

  • [ ! -d "${f}" ] && continue to skip non-directories (note: this will still match symlinks that point at directories)
  • cd "${f}" || continue to skip directories we can't enter (e.g: permissions)
  • pushd "${f}" / popd to avoid relative cd return attempts
for f in *; do
    # skip non-directories
    [ ! -d "$f" ] && continue
# skip processing for directories we can't enter (e.g: permissions)
pushd "$f" || continue

echo "hi"
pwd

popd

done

Attie
  • 20,734