How to properly process and print files with spaces in bash How to properly process and print files with spaces in bash shell shell

How to properly process and print files with spaces in bash


To illustrate the difference between "$@" and $@, let us consider the two following functions:

f() { for i in $@; do echo $i; done; }g() { for i in "$@"; do echo $i; done; }

When calling these function with the parameters a "b c" "d e" the result will be

  • function f

f a "b c" "d e" a b c d e

  • function g g a "b c" "d e" a b c d e

So when "$@" is within double quotes, the expansion keeps each parameter in a separate word (even if the parameter contains one or more space).When $@ (without double quotes) is expanded, a parameter with a space will be considered as two words.

In your script, you need also to surround argdir and file with double quotes. It is useful when the name of a directory or a file contains space so the name will be considered as a single value. Below your script modified.

#! /bin/bash -urecls () {    # store current working directory    # issues: seems bad to have cwd defined up here and used down below in getAbsolutePath -- too much coupling    cwd=$PWD    # get absolute path of arg    argdir=`getAbsolutePath "$@"`    # check if it exists    if [ ! -e "$argdir" ]; then        echo "$argdir does not exist"        return 1    fi    echo "$argdir exists"    # check if it's a directory    if [ ! -d "$argdir" ]; then        echo "$argdir is not a directory"        return 2    fi    echo "$argdir is a directory"    tab=""    recls_internal "$argdir"    return 0}recls_internal () {    for file in "$@"; do        echo -n "$tab${file##/*/}"        if [ -d "$file" ]; then            # print forward slash to show it's a directory            echo "/"            savedtab=$tab            tab="$tab    "            recls_internal "$file"/*            tab=$savedtab        else            # if not a directory, print a new line            echo ""        fi       done}getAbsolutePath () {    if [ -z ${1##/*} ]; then        echo "$1"    else        echo "$cwd/$1"    fi}