bash 遍历目录的shell脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10610955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:16:59  来源:igfitidea点击:

Shell script to traverse directories

bash

提问by Jason

I'm working on a project that requires batch processing of a large number of image files. To make things easier, I've written a script that will create ndirectories and move mfiles to them based on user input.

我正在做一个需要批量处理大量图像文件的项目。为了使事情更容易,我编写了一个脚本,该脚本将根据用户输入创建n目录并将m文件移动到这些目录中。

My issue is to now understand directory traversal via shell script.

我的问题是现在通过 shell 脚本了解目录遍历。

I've added this snippet at the end of the sort script described above

我在上面描述的排序脚本的末尾添加了这个片段

dirlist=$(find  -mindepth 1 -maxdepth 1 -type d)

for dir in $dirlist
do
  cd $dir
  echo $dir
  ls
done

When I ran it inside a Pano2 folder, whcih contains two inner folders, I always got an error

当我在 Pano2 文件夹中运行它时,其中包含两个内部文件夹,我总是遇到错误

./dirTravel: line 9: cd: Pano2/05-15-2012-2: No such file or directory

However, after that, I get the file listing from specified directory.

但是,在那之后,我从指定的目录中获取了文件列表。

What is the reason behind the warning? If I add cd ../after lsI get the listing of the folders inside Pano2/, but not the files themselves.

警告背后的原因是什么?如果我cd ../ls获得 Pano2/ 中的文件夹列表而不是文件本身之后添加。

采纳答案by Nate Kohl

My guess is that you're going in two levels deep, but only coming back up one level. Try adding a cd ../..after the ls, or use pushdand popdinstead.

我的猜测是,您将进入两个级别的深度,但只能返回一个级别。尝试在cd ../..之后添加ls, 或使用pushdandpopd代替。

For example:

例如:

for dir in $dirlist
do
  pushd $dir
  echo $dir
  ls
  popd
done

As @shellter points out, if those directories have spaces, then something like this might work better:

正如@shellter 指出的那样,如果这些目录有空格,那么这样的事情可能会更好:

find  -mindepth 1 -maxdepth 1 -type d | while read -r dir
do
  pushd "$dir"  # note the quotes, which encapsulate whitespace
  echo $dir
  ls
  popd
done

回答by Jonathan Leffler

I recommend using a sub-shell to switch directories:

我建议使用子shell来切换目录:

dirlist=$(find  -mindepth 1 -maxdepth 1 -type d)

for dir in $dirlist
do
  (
  cd $dir
  echo $dir
  ls
  )
done

The code inside the sub-shell won't affect the parent shell, so it can change directory anywhere without giving you any issues about 'how to get back'.

子 shell 中的代码不会影响父 shell,因此它可以在任何地方更改目录,而不会给您任何有关“如何返回”的问题。

This comes with the standard caveat that the whole process is fraught if your directory names can contain spaces, newlines or other unexpected and awkward characters. If you keep with the portable filename character set ([-_.A-Za-z0-9]) you won't run into problems as written.

这附带了一个标准警告,即如果您的目录名称可以包含空格、换行符或其他意外和尴尬的字符,则整个过程会充满挑战。如果您使用可移植文件名字符集 ( [-_.A-Za-z0-9]),您将不会遇到书面问题。

回答by jordanm

There really isn't any reason to cd to the directory to run the lscommand. The following should work:

确实没有任何理由 cd 到目录来运行ls命令。以下应该工作:

find "" -mindepth 1 -maxdepth 1 -type d -exec ls {} \;

If that was just an example, and you really run other commands that depend on the working directory, you can use bash -c with -exec:

如果这只是一个示例,并且您确实运行了依赖于工作目录的其他命令,则可以将 bash -c 与 -exec 结合使用:

find "" -mindepth 1 -maxdepth 1 -type d -exec bash -c 'cd ""; echo ""; ls' -- {} \;

The bash -c call spawns a subshell, so you don't need to worry about it changing the directory of the current shell.

bash -c 调用会生成一个子shell,因此您无需担心它会更改当前shell 的目录。