我有一个文件夹,里面有一些目录和一些文件(其中一些是隐藏的,以点开头)。
循环遍历所有文件和目录,但我只想循环遍历目录。我该如何做到这一点?
for d in *; do
echo $d
done
循环遍历所有文件和目录,但我只想循环遍历目录。我该如何做到这一点?
for d in */ ; do
echo "$d"
done
for d in */ ; do
[ -L "${d%/}" ] && continue
echo "$d"
done
if [[ "$f" = "*" ]]; then continue; fi
- Piskvor left the building-d
测试将为假,所以不用担心,也不必与模式进行比较。 - Kusalananda#!/usr/bin/env bash
for d in */; do
# Will print */ if no directories are available
echo "$d"
done
#!/usr/bin/env bash
for f in *; do
if [ -d "$f" ]; then
# Will not run if no directories are available
echo "$f"
fi
done
f
是否为一个目录,如果条件返回true,则输出f
。如果f
等于*/
,则echo "$f"
将不会执行。shopt -s nullglob
命令。 - chorobafind
命令,并将其传递给while read
。shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do
echo "$d"
done
使用shopt -u dotglob
来排除隐藏目录(或在zsh中使用setopt dotglob
/unsetopt dotglob
)。
IFS=
用于避免拆分包含$IFS
之一的文件名,例如:'a b'
有关更多find
选项,请参见下方的AsymLabs答案。
while IFS= read -r d; do
if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)
find
的输出。即使将IFS
设置为空字符串,它仍然会在包含换行符的文件名上出错。尽管这些文件名很少见,但如果能够轻松编写处理所有文件名的代码,那就没有理由编写不能处理的代码。 - Kusalanandafind
的输出”是误导性的。只要输出元素不以换行符(默认)而是以空字符结尾,这样做是可以的。这将需要将IFS更改为0字节,或者使用read -d
来处理它。然后,即使文件名包含换行符,也可以正确处理。 - Jonathan KomarIFS
更改为包含空字符意味着可以在变量中存储这些字符的shell。而bash
shell并不支持这样做。read -d
是特定于bash
的(xargs -0
可能更适合,因为它不依赖于shell,尽管它仍然不是标准的)。我的观点是,如果你能以一种可移植和安全的方式正确地完成任务,那么就没有理由使其不可移植和/或不安全。find
命令提供了-exec
选项,正是为了让用户能够迭代处理找到的路径名! - Kusalanandafind . -maxdepth 1 -type d -exec echo {} \;
bash
中使用shopt -s dotglob
来包含隐藏目录。您的命令还将包括.
。另外请注意,-maxdepth
不是一个标准选项(-prune
是)。 - Stéphane Chazelasdotglob
选项很有趣,但是dotglob
只适用于使用*
。find .
命令总是会包括隐藏的目录(以及当前目录)。 - rubo77 find -path './*' -prune -type d
find -L -path './*' -prune -type d
find -path './*' -prune -type d -print0 | xargs -0 <cmds>
排除隐藏目录:
find -path './[^.]*' -prune -type d
find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"
-maxdepth 1
选项在所有符号链接上会引发错误:“文件名”符号链接层级太多。 - rubo77... -print0 | xargs -0 ...
。 - Anthonfind * ....
。 - Anthonxargs
在一个命令中只能执行一个操作,所以我认为您需要创建一个函数,然后在xargs
中调用该函数。您能提供一个示例吗? - rubo77find * | while read file; do ...
的函数对每个目录执行某些操作。 - rubo77find -type d
- Hopping Bunnyfor name in */ .*/ ; do printf '%s is a directory\n' "$name"; done
for name in *; do
if [ -d "$name" ] && [ ! -L "$name" ]; then
printf '%s is a directory\n' "$name"
fi
done
*/ .*/
可以工作,但同时会显示文件夹.
和..
;而在中,它不会显示这些文件夹,但如果文件夹中没有隐藏文件,则会报错。
shopt -s dotglob nullglob
for name in */ ; do printf '%s is a directory\n' "$name"; done
shopt -u dotglob nullglob
find
命令配合-exec
选项来遍历目录并调用执行选项中的函数。dosomething () {
echo "doing something with $1"
}
export -f dosomething
find ./* -prune -type d -exec bash -c 'dosomething "$0"' {} \;
shopt -s dotglob
或 shopt -u dotglob
来包含/排除隐藏目录nullglob
和dotglob
shell选项在这里不会起任何作用,因为shell从不用于进行通配符匹配。如果没有指定搜索路径,-path './*'
测试对所有路径名都为真,因为它们都在.
目录下(GNU find
的默认搜索路径)。 - Kusalananda-path
移除了。 - rubo77dotglob
选项会生效。 - rubo77仅列出目录。如果需要,在名称中包括空格和隐藏目录-A
:
grep '/$' <(ls -AF)
| xargs -I{} echo {}
| while read; do echo $REPLY; done
for i in */ .[^.]*/; do
[ -h "${i%?}" ] || echo $i
done
[ -h "${i%?}" ]
吗? - rubo77?
- 匹配任意单个字符。类似于${i%/}
。去除末尾的斜杠 - 目录指示符。如果没有这个操作,test
命令中的 -h
和 -L
选项将无法正常工作。 - nezabudkatopdir=.
find "$topdir" ! -path "$topdir" -prune -type d -exec sh -c '
for dirpath do
# user code goes here, using "$dirpath"
printf "\"%s\" is a directory\n" "$dirpath"
done' sh {} +
.
)。将topdir
设置为其他路径名以在另一个目录上使用它。
find
实用程序被要求忽略与起始搜索路径相同的路径名! -path "$topdir"
,然后剪除(不进入)找到的任何其他路径名。这将限制搜索范围仅在由$topdir
引用的目录中。-type d
),并使用批处理作为参数执行sh -c
脚本。sh -c
脚本是我们希望对所有目录执行的代码,因此它遍历给定的参数并对每个参数执行所需的操作。如果需要使用bash
执行某些操作,则显然应该使用bash -c
。
sh -c
脚本可以单独分离成自己的脚本,如下所示:#!/bin/sh
for dirpath do
# user code goes here, using "$dirpath"
printf '"%s" is a directory\n' "$dirpath"
done
find
被调用,如下所示:find "$topdir" ! -path "$topdir" -prune -type d -exec ./myscript.sh {} +
find "$topdir"/*
而不需要 ! -path "$topdir"
。 - rubo77"$topdir"/*
匹配的所有路径名。这个模式不会匹配 $topdir
下的隐藏名称,因此也不会在该目录中找到任何隐藏的子目录。 - Kusalananda
for d in */ .*/ : do ...
循环遍历隐藏文件。但是如何在循环中排除../
? - rubo77set -P
只会影响改变目录的命令。http://sprunge.us/TNac - Chris Down**/
。 - Aaron*/ ;
吗?我对代码的作用和功能还不太理解。 - timbram*
是通配符,代表“任何东西”。/
表示“任何东西”必须是一个目录才能匹配通配符表达式。;
是for循环的一部分,它将do
和for
分开。 - chorobashopt -s nullglob
以防止没有目录时出现问题。 - rubo77dir1
),而不是完整的目录路径(例如/home/user/dir1
)。 - Raleigh L.