识别 bash 中的文件夹

识别 bash 中的文件夹

我试图学习如何仅识别主级别文件夹中的文件夹。例子:

  • 主要的
  • -文件夹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

但根据您想要执行的操作,您还可以使用-execfind 选项对每个文件执行命令。

答案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"

相关内容