我是 Linux 新手,我正在尝试编写一个 Bash 脚本,它将目录的内容复制到将创建的备份文件夹,而不使用 -r 开关。我假设目录的最大深度是 2 。我在脚本中放置了一些 echo,我注意到 for 循环将第一个也是唯一的参数作为当前文件夹的路径 - 它绝对忽略目录中的所有文件。我尝试更改代码几次但没有成功。有语法错误吗?逻辑不对吗?我很想得到答案。多谢!
pwd > route
r=$(<route)
cd ..
if [ ! -d backup ]; then
mkdir backup
fi
cd backup
pwd > buroute
BUrout=$(<buroute)
cd "$r"
for i in $r; do
if [ -f $i ]; then
cp $i "$BUrout"
fi
if [ -d $i ]; then
if [ $i == $r ]; then
continue
fi
cd "$i"
pwd > current
cur=$(<current)'/'
for file in "$cur"; do
if [ -f "$file" ]; then
cp $file "$BUrout"
fi
done
cd ..
fi
done
答案1
我不太明白为什么你不能只使用cp -r
orrsync -a
来实现这个目的,除非你明确想要扁平化目录结构,但没关系。
您需要做很多工作来获取子目录的路径: cd
进入目录、pwd
进入文件,然后将该文件读入变量。相反,您可以只使用eg BUrout="$PWD/backup"
($PWD
保存当前工作目录的路径名)。
您将永远不会处理任何文件,因为您的循环是在目录名称上。你想要的可能是for i in "$r"/*; do
, 类似地在第二个循环中。
总是双引号你的变量扩展!例如if [ "$i" = "$r" ]
(注意也是 single =
,而不是 double )。参见两个“为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?“ 和 ”忘记在 bash/POSIX shell 中引用变量的安全隐患”
您的脚本不应需要单个cd
.进入和退出目录的脚本是真的很难调试。
除此之外,没有语法错误,而且逻辑似乎是正确的。
我可以建议这样的东西,它仍然使用相同的循环逻辑和与您的代码使用的大部分相同的测试,但没有调用,cd
也不必过多地修改目录名称:
#!/bin/sh
source="$1"
dest="$2"
mkdir -p "$dest" # creates destination directory if not already exists
for name in "$source"/*; do
if [ -f "$name" ]; then
cp "$name" "$dest"
elif [ -d "$name" ]; then
for name2 in "$name"/*; do
if [ -f "$name2" ]; then
cp "$name2" "$dest"
fi
done
fi
done
或者,使用似乎对某些人有吸引力的快捷语法:
#!/bin/sh
source="$1"
dest="$2"
mkdir -p "$dest" # creates destination directory if not already exists
for name in "$source"/*; do
[ -f "$name" ] && { cp "$name" "$dest"; continue; }
[ ! -d "$name" ] && continue
for name2 in "$name"/*; do
[ -f "$name2" ] && cp "$name2" "$dest"
done
done
该脚本有两个参数,源目录和目标/目标目录:
$ ./script mydir some_new_backup_dir
不会尝试检查任何命令是否cp
会覆盖目标目录中的现有文件。
另请注意,这两个脚本都是/bin/sh
脚本。他们不使用特定于bash
shell 的东西。
假设目标目录存在,这或多或少相当于
find source_dir -maxdepth 2 -type f -exec cp {} target_dir ';'