【问题标题】:Archive old files only AND re-construct folder tree in archive仅存档旧文件并在存档中重新构建文件夹树
【发布时间】:2013-09-09 12:58:49
【问题描述】:
我想将我所有超过 1000 天的文件(分布在各个子文件夹中)从 /home/user/documents 移动到 /home/user/archive。我试过的命令是
find /home/user/documents -type f -mtime +1000 -exec rsync -a --progress --remove-source-files {} /home/user/archive \;
问题是,(可以理解)所有文件最终都被移动到单个文件夹 /home/user/archive 中。但是,我想要的是在 /home/user/archive 中重新构建 /home/user/documents 下面的文件树。我认为这应该可以通过简单地用另一个字符串替换一个字符串来实现,但是如何呢?用于此目的的命令是什么?
谢谢!
【问题讨论】:
标签:
linux
bash
copy
find
backup
【解决方案1】:
我会选择这条路线而不是rsync:
-
更改目录,以便我们可以处理相对路径名而不是绝对路径名:
cd /home/user/documents
-
运行find 命令并将输出提供给cpio,请求它对文件进行硬链接(-l),创建前导目录(-d)并保留属性(-m )。 -print0 和 -0 选项使用空值作为记录终止符,以正确处理其中包含空格的文件名。 cpio 的 -l 选项使用链接而不是实际复制文件,因此使用的额外空间非常少(正是新目录所需的空间)。
find . -type f -mtime +1000 -print0 | cpio -dumpl0 /home/user/archives
-
重新运行您的 find 命令并将输出提供给 xargs rm 以删除原件:
find . -type f -mtime +1000 -print0 | xargs -0 rm
【解决方案2】:
这也是一个脚本。
#!/bin/bash
[ -n "$BASH_VERSION" ] && [[ BASH_VERSINFO -ge 4 ]] || {
echo "You need Bash version 4.0 to run this script."
exit 1
}
# SOURCE=/home/user/documents/
# DEST=/home/user/archive/
SOURCE=$1
DEST=$2
declare -i DAYSOLD=10
declare -a DIRS=()
declare -A DIRS_HASH=()
declare -a FILES=()
declare -i E=0
# Check directories.
[[ -n $SOURCE && -d $SOURCE && -n $DEST && -d $DEST ]] || {
echo "Source or destination directory may be invalid."
exit 1
}
# Format source and dest variables properly:
SOURCE=${SOURCE%/}
DEST=${DEST%/}
SOURCE_LENGTH=${#SOURCE}
# Copy directories first.
echo "Creating directories."
while read -r FILE; do
DIR=${FILE%/*}
if [[ -z ${DIRS_HASH[$DIR]} ]]; then
PARTIAL=${DIR:SOURCE_LENGTH}
if [[ -n $PARTIAL ]]; then
TARGET=${DEST}${PARTIAL}
echo "'$TARGET'"
mkdir -p "$TARGET" || (( E += $? ))
chmod --reference="$DIR" "$TARGET" || (( E += $? ))
chown --reference="$DIR" "$TARGET" || (( E += $? ))
touch --reference="$DIR" "$TARGET" || (( E += $? ))
DIRS+=("$DIR")
fi
DIRS_HASH[$DIR]=.
fi
done < <(exec find "$SOURCE" -mindepth 1 -type f -mtime +"$DAYSOLD")
# Copy files.
echo "Copying files."
while read -r FILE; do
PARTIAL=${FILE:SOURCE_LENGTH}
cp -av "$FILE" "${DEST}${PARTIAL}" || (( E += $? ))
FILES+=("$FILE")
done < <(exec find "$SOURCE" -mindepth 1 -type f -mtime +"$DAYSOLD")
# Remove old files.
if [[ E -eq 0 ]]; then
echo "Removing old files."
rm -fr "${DIRS[@]}" "${FILES[@]}"
else
echo "An error occurred during copy. Not removing old files."
exit 1
fi