我正在尝试编写一个脚本来做到这一点:假设我有一个名为testdir
的目录,它看起来像这样:
**testdir**/
├── **jfjfjddsdsdsds** (directory)
├── jfjfjfjf (file)
├── kdskskk
├── kkkkkkkkk
├── **sadadasad**
│ ├── assd
│ ├── **kakak**
│ ├── **ksja**
│ ├── **lklksl**
│ └── lskal
└── **skdjsjlsj**
├── **djfldjlfjd**
│ ├── eiuru
│ ├── rhhrhshs
│ ├── rhrhshs
│ └── shhdshsd
├── jjskskk
├──** kdjskdjfks**
├── kjjrjjrj
└── kjskjd
字符串
文件名是完全随机的,我想写一个脚本,它需要一个目录路径,并重命名每个子目录和每个文件,看起来像这样:
**testdir**/
├── **dir1**
├── file1
├── file2
├── file3
├── **dir2**
│ ├── file1
│ ├── **dir1**
│ ├── **dir2**
│ ├── **dir3**
│ └── file2
└── **dir3**
├── **dir1**
│ ├── file1
│ ├── file2
│ ├── file3
│ └── file4
├── file1
├──** dir2**
├── file2
└── file3
型
所以它按顺序重命名每个目录-第一个成为“dir 1”,第二个成为“dir 2”,等等。对于文件也是一样的-“file 1”,“file 2”,它还从开始目录写入文件的深度。并且应该递归地为每个目录执行,在此过程中重置“文件计数器”和“目录计数器”。
我的脚本看起来像这样:
#!/bin/bash
#see executed comands when run
set -xeuo pipefail
rename() {
# $1 - directory path, $2 - directory depth
fileCounter=1
dirCounter=1
#enter a directory
cd "$1"
for file in *
do
if [[ -f "$file" ]]
then
#if its a regular file, write its depth and rename it
echo "(I am file, my depth is $2)" > "$file"
mv "$file" "file$fileCounter" 2>/dev/null
#increase the counter
(( fileCounter++ ))
elif [[ -d "$file" ]]
then
#its a directory - rename and call recursion
mv "$file" "dir$dirCounter" 2>/dev/null
#call recursion with depth + 1
rename "dir$dirCounter" "(( $2 + 1 ))"
#increase the counter
(( dirCounter++ ))
#else
#do nothing, its not a regular file or a directory
fi
done
}
if [[ $# -gt 1 ]]
then
echo "Too many arguments >:("
exit 1
fi
if [[ ! -d "$1" ]]
then
echo "The directory doesn't exist"
exit 1
fi
#start recursion
rename "$1" 0
型
然而,当我执行脚本时,它似乎在第一次递归调用后停止,所以我得到如下输出:
+ [[ 1 -gt 1 ]]
+ [[ ! -d testdir/ ]]
+ rename testdir/ 0
+ fileCounter=1
+ dirCounter=1
+ cd testdir/
+ for file in *
+ [[ -f jfjfjddsdsdsds ]]
+ echo '(I am file, my depth is 0)'
+ mv jfjfjddsdsdsds file1
+ (( fileCounter++ ))
+ for file in *
+ [[ -f jfjfjfjf ]]
+ echo '(I am file, my depth is 0)'
+ mv jfjfjfjf file2
+ (( fileCounter++ ))
+ for file in *
+ [[ -f kdskskk ]]
+ [[ -d kdskskk ]]
+ mv kdskskk dir1
+ rename dir1 '(( 0 + 1 ))'
+ fileCounter=1
+ dirCounter=1
+ cd dir1
+ for file in *
+ [[ -f * ]]
+ [[ -d * ]]
+ (( dirCounter++ ))
+ for file in *
+ [[ -f kkkkkkkkk ]]
+ [[ -d kkkkkkkkk ]]
+ for file in *
+ [[ -f sadadasad ]]
+ [[ -d sadadasad ]]
+ for file in *
+ [[ -f skdjsjlsj ]]
+ [[ -d skdjsjlsj ]]
型
树看起来是这样的:
testdir/
├── dir1
├── file1
├── file2
├── kkkkkkkkk
├── sadadasad
│ ├── assd
│ ├── kakak
│ ├── ksja
│ ├── lklksl
│ └── lskal
└── skdjsjlsj
├── djfldjlfjd
│ ├── eiuru
│ ├── rhhrhshs
│ ├── rhrhshs
│ └── shhdshsd
├── jjskskk
├── kdjskdjfks
├── kjjrjjrj
└── kjskjd
型
因此,脚本不会继续进行递归,甚至不会重命名最上层目录中的所有常规文件
我看不到脚本中的错误,为什么递归停止了?
1条答案
按热度按时间vs3odd8k1#
为什么递归会停止?
因为在你下降
cd "$1"
之后,你不会从它出来。一个简单的脏修复方法是在子shell中运行
( rename "dir$dirCounter" "(( $2 + 1 ))" )
。您可能还对pushd
和popd
感兴趣。或者,您可以将目录位置的当前深度作为另一个rename
参数传递。我会选择最后一个选项,因为cd
依赖于全局状态-当前目录-这就是为什么它会变得令人困惑。