3

私は単純な再帰的な ls プログラムを bash で書いています (これはあまり経験がないので、遠慮なく残忍にしてください)。

このプログラムは、各ファイル (場合によってはディレクトリ) を別々の行に出力することになっています。新しいディレクトリが入力されるたびに、出力が 4 つのスペース分シフトされ、ツリーのような出力が得られます。

現在、スペースを含むファイルを正しく出力せず、ディレクトリの後にスラッシュを付けません。(詳細は以下をご覧ください。)

コード

recls () {

    # 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    "
            myls_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

}

出力

スクリプトは、 というフォルダに含まれていますbash-practice。するとrecls .、次の出力が得られます。

./
    myls.sh
    myls.sh~
    recdir.sh
    recls.sh
    recls.sh~
    sample
    document.txt
    sample-folder
        sample-stuff
            test-12.txt
        test-1.txt
        test-2.txt
        sort-test.txt
        sort-text-copy.txt
        test-5-19-14-1

問題

ご覧のとおり、インデントは適切に機能していますが、2 つの問題があります。

1) スペースが含まれているため、ファイルsample document.txtが 2 行にまたがっています。

2)すべてのディレクトリの前にスラッシュが必要ですが、何らかの理由で最初のディレクトリでしか機能しません。

試みられた解決策

(1) を修正するために、内部ファイル区切り文字を保存して、次のように改行文字に置き換えてみました。

...
tab=""
savedIFS=$IFS
IFS="\n"
recls_internal $argdir
IFS=$savedIFS
return 0

しかし、これはまったく機能しませんでした。最初のフォルダー以上は表示されませんでした。明らかに私の物事の理解は正しくありません。

(2) については、意図したとおりに動作しない理由がわかりません。

結論

bash は、他のほとんどのプログラミング言語 (シェル スクリプト言語) よりも珍しい構文を持っているように思われるため、私にとっては難しいので、私の過ちと解決策についての洞察をいただければ幸いです。

更新 #1

mklement0 が提案したサイトhttp://www.shellcheck.comに行きましたが、そのヒントは基本的にすべて二重引用符でした。を二重引用符で囲む"$@"と、プログラムはファイルを正しく出力しましたsample document.txtが、その直後に " binary operator expected" エラーが発生しました。以下は、現在の外観を印刷したものです。

ここに画像の説明を入力

更新 #2 [問題は解決しましたか?]

myls_internalOK、タイプミスがあったため、再帰時に呼び出された関数の以前のバージョンにデフォルト設定されていたことが判明しました。この以前のバージョンでは、ディレクトリをスラッシュでマークしていませんでした。「更新」セクションのエラー メッセージも修正されました。ラインを変えました

myls_internal "$file/*"

recls_internal $file/*

そして今、それは正しく動作しているようです。誰かが回答を書いている途中である場合でも、「$ @」を引用してスペースの問題を修正する方法の仕組みがよくわからないので、あなたの洞察に感謝します。

固定コード:

recls () {

    # 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

}

固定出力:

ここに画像の説明を入力

アップデート #3

この線

recls_internal $file/*

代わりに

recls_internal "$file"/*

スペースを含むディレクトリを正しく処理します。cs 350それ以外の場合は、含むHomework1.pdfなどのフォルダHomework2.pdfに展開されます

cs 350/Homework1.pdf 350/Homework2.pdf

いつあるべきか

cs 350/Homework1.pdf cs 350/Homework2.pdf

おもう?何が起こっているのかの詳細はわかりませんが、それで修正されたようです。

4

1 に答える 1