我试图学习如何仅识别主级别文件夹中的文件夹。例子:
- 主要的
- -文件夹1
- -文件夹2
- -文件夹3
我从这个脚本开始:
#!/bin/bash
LOCATION="/mnt/test/build/"
for folder in $(ls $LOCATION); do
echo "$folder"
done
但是,当我运行脚本时,它将回显整个内容,如果文件夹内有空格,则名称将添加到两行中。如果我将回显行从 更改"$folder"
为'$folder'
,则只会回显文件夹。任何有建议性的文章也很棒。
答案1
不要ls
用于简单地迭代目录的内容,请使用 globbing:
#!/bin/bash
LOCATION="/mnt/test/build/"
for folder in "$LOCATION"/*; do
[ -d "$folder" ] || continue
echo "$folder"
done
该[ -d "$folder" ]
命令测试是否$folder
是目录。如果不是,则该条目将被跳过continue
。请注意$LOCATION
和周围的引号$folder
,它们可以防止脚本在$LOCATION
包含空格时中断。
如果您确实需要处理 的内容ls
,请使用类似以下内容的内容:
ls "$LOCATION" | while read folder; do
echo "$folder"
done
如果您有额外的限制,即需要在循环之后访问循环内的变量,请使用 Bash 进程替换:
while read folder; do
echo "$folder"
done < <(ls "$LOCATION")
Bash 手册位于http://www.gnu.org/software/bash/manual/。
答案2
不解析输出ls
。您不需要ls
列出目录的内容:您可以使用 shell 通配符。
当您编写 时$(ls $LOCATION)
,命令的输出ls
将在其中包含空格的地方拆分为单独的单词。这就是为什么你的命令用空格破坏文件名的原因。您可以修改该IFS
变量以避免将空格视为分隔符,但无法区分用于分隔文件名的换行符和文件名中的换行符,因此您无法完全避免问题。此外,分割产生的每个单词都被视为一个 glob(即通配符模式),并由匹配文件列表(如果有)替换。 shell 脚本编写的一个简单规则是:"$foo"
始终在变量替换和命令替换两边加上双引号"$(foo)"
。双引号可以防止分割和通配符。
以下代码片段与您的循环等效,只是它不会破坏文件名,并且会打印每个文件的完整路径。
for x in "$LOCATION"/*; do
echo "$x"
done
如果您想要相对于 的路径$LOCATION
,一种方法是首先更改为目标目录。
cd "$LOCATION"
for x in *; do
echo "$x"
done
另一种方法是从文件名中去掉前缀。
for full_path in "$LOCATION"/*; do
relative_name=${full_path#"$LOCATION/"}
echo "$relative_name"
done
这将打印目标目录中所有文件的名称。如果您只想列出子目录(包括目录的符号链接),请将 a 添加/
到 glob 模式以限制匹配。
for full_path in "$LOCATION"/*/; do
relative_name=${full_path#"$LOCATION/"}
relative_name=${relative_name%/}
echo "$relative_name"
done
如果您不希望包含符号链接,请对循环内的目录进行显式测试。
for full_path in "$LOCATION"/*/; do
if ! [ -d "$full_path" ]; then continue; fi
relative_name=${full_path#"$LOCATION/"}
relative_name=${relative_name%/}
echo "$relative_name"
done
答案3
查找您所在级别以下的所有目录
find . -type d
如果你想将自己限制在一个级别
find . -type d -maxdepth 1 -mindepth 1
编辑
我错过了你问题的一部分:
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for dir in $( find . -type d -maxdepth 1 -mindepth 1 ) ; do
echo ${dir}
done
IFS=$SAVEIFS
但根据您想要执行的操作,您还可以使用-exec
find 选项对每个文件执行命令。
答案4
此命令将仅直接在 $LOCATION 中查找所有目录。它不会列出所述目录的任何内容。
#!/bin/bash
LOCATION="/mnt/test/build/"
find "$LOCATION" -mindepth 1 -maxdepth 1 -type d
如果您只想打印相对路径而不是绝对路径,请使用以下命令:
find "$LOCATION" -mindepth 1 -maxdepth 1 -type d -printf "%f\n"