私は単純な再帰的な 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_internal
OK、タイプミスがあったため、再帰時に呼び出された関数の以前のバージョンにデフォルト設定されていたことが判明しました。この以前のバージョンでは、ディレクトリをスラッシュでマークしていませんでした。「更新」セクションのエラー メッセージも修正されました。ラインを変えました
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
おもう?何が起こっているのかの詳細はわかりませんが、それで修正されたようです。