根据文件名将文件移动到正确的日期目录
Move files to correct date directories based on filename
我的一些文件在不正确的目录中,我正在尝试将它们移动到正确的位置。
示例:
目录 20180622 将仅包含名称中包含 20180622 的文件名
如果 20180622 目录包含名称中包含 20180623 的文件,那么它是一个放错位置的文件,应该转到相应的正确目录即 20180623
目录结构是固定的(幸好)
date1/a/b/someprefix.date1.somesuffix #no problem
date1/a/b/someprefix.date2.somesuffix # problem
date2/c/d/someprefix.date2.somesuffix # no problem
date2/e/f/someprefix.date3.somesuffix # problem
date1/a/b/someprefix.date1.somesuffix
date2/a/b/someprefix.date2.somesuffix # problem fixed
date2/c/d/someprefix.date2.somesuffix
date3/e/f/someprefix.date3.somesuffix #problem fixed
使用 find . -type f
我得到了所有文件的列表,但不知道如何 mv
文件到正确的位置。
someprefix
可以是任何东西(它也可能包含一个点,所以 cut 不是从文件名中提取日期的好方法) $f =~ (.*)(201[5-8][0-9][0-9][0-9][0-9][0-9])(.*)
是我试图从文件名中提取日期的方法
应该很容易处理,你只需要一个循环和一个if。
for path in $(find . -type f); do
dirdate=$(echo $path | cut -d '/' -f 2)
filedate=$(basename $path | cut -d '.' -f 2)
if [[ $dirdate != $filedate ]]; then
mv $path $(dirname $path | sed "s/$dirdate/$filedate/g")
fi
done
这里的想法非常简单:它在文件中循环获取整个文件路径 (./date1/a/b/prefix.date.suffix
) 并检查 date1
是否等于 date
。如果不是,它将文件移动到 date1
被 date
替换的相同路径。
编辑评论
如果你想为你的文件名处理多个分隔符,你只需要更改 filedate=
行,如:
filedate=$(basename $path | awk -F'[._\-]' '{print }' 2> /dev/null)
它有点棘手,但假设它是 Bash。
2> /dev/null
是让 awk
的警告静音。
不幸的是,使用 bash 正则表达式匹配,您无法提取 所有 子匹配项,所以我回退到 grep 来查找所有日期。
find . -type f -print0 |
while IFS= read -d "" -r filename; do
mapfile -t dates < <(echo "$filename" | grep -Eo '\<201[5-8][0-9]{4}\>')
if [[ ${#dates[@]} -eq 2 ]] && [[ ${dates[0]} != ${dates[1]} ]]; then
destdir=$(dirname "$filename" | sed "s/${dates[0]}/${dates[1]}/")
mkdir -p "$destdir"
mv -v "$filename" "$destdir"
fi
done
测试:
$ tree
.
├── 20180621
│ └── a
│ └── b
│ ├── a.20180621.txt
│ └── foo.20180701.bar
└── 20180701
└── c
└── d
└── ok.20180701
6 directories, 3 files
我们有一个文件需要移动
$ find . -type f -print0 |
while IFS= read -d "" -r filename; do
mapfile -t dates < <(echo "$filename" | grep -Eo '\<201[5-8][0-9]{4}\>')
if [[ ${#dates[@]} -eq 2 ]] && [[ ${dates[0]} != ${dates[1]} ]]; then
destdir=$(dirname "$filename" | sed "s/${dates[0]}/${dates[1]}/")
mkdir -p "$destdir"
mv -v "$filename" "$destdir"
fi
done
'./20180621/a/b/foo.20180701.bar' -> './20180701/a/b/foo.20180701.bar'
结果
$ tree
.
├── 20180621
│ └── a
│ └── b
│ └── a.20180621.txt
└── 20180701
├── a
│ └── b
│ └── foo.20180701.bar
└── c
└── d
└── ok.20180701
8 directories, 3 files
不依赖 grep,这是对 Arount 回答的一个调整:
find 20+([0-9])/ -type f -print0 |
while IFS= read -d "" -r filename; do
dirdate=${filename%%/*}
if [[ "$(basename "$filename")" =~ 20[0-9]{6} ]]; then
filedate=${BASH_REMATCH[0]}
if [[ $dirdate != $filedate ]]; then
dest=${filename/$dirdate/$filedate}
echo mkdir -p "$(dirname "$dest")"
echo mv -v "$filename" "$dest"
fi
fi
done
我的一些文件在不正确的目录中,我正在尝试将它们移动到正确的位置。
示例:
目录 20180622 将仅包含名称中包含 20180622 的文件名
如果 20180622 目录包含名称中包含 20180623 的文件,那么它是一个放错位置的文件,应该转到相应的正确目录即 20180623 目录结构是固定的(幸好)
date1/a/b/someprefix.date1.somesuffix #no problem
date1/a/b/someprefix.date2.somesuffix # problem
date2/c/d/someprefix.date2.somesuffix # no problem
date2/e/f/someprefix.date3.somesuffix # problem
date1/a/b/someprefix.date1.somesuffix
date2/a/b/someprefix.date2.somesuffix # problem fixed
date2/c/d/someprefix.date2.somesuffix
date3/e/f/someprefix.date3.somesuffix #problem fixed
使用 find . -type f
我得到了所有文件的列表,但不知道如何 mv
文件到正确的位置。
someprefix
可以是任何东西(它也可能包含一个点,所以 cut 不是从文件名中提取日期的好方法) $f =~ (.*)(201[5-8][0-9][0-9][0-9][0-9][0-9])(.*)
是我试图从文件名中提取日期的方法
应该很容易处理,你只需要一个循环和一个if。
for path in $(find . -type f); do
dirdate=$(echo $path | cut -d '/' -f 2)
filedate=$(basename $path | cut -d '.' -f 2)
if [[ $dirdate != $filedate ]]; then
mv $path $(dirname $path | sed "s/$dirdate/$filedate/g")
fi
done
这里的想法非常简单:它在文件中循环获取整个文件路径 (./date1/a/b/prefix.date.suffix
) 并检查 date1
是否等于 date
。如果不是,它将文件移动到 date1
被 date
替换的相同路径。
编辑评论
如果你想为你的文件名处理多个分隔符,你只需要更改 filedate=
行,如:
filedate=$(basename $path | awk -F'[._\-]' '{print }' 2> /dev/null)
它有点棘手,但假设它是 Bash。
2> /dev/null
是让 awk
的警告静音。
不幸的是,使用 bash 正则表达式匹配,您无法提取 所有 子匹配项,所以我回退到 grep 来查找所有日期。
find . -type f -print0 |
while IFS= read -d "" -r filename; do
mapfile -t dates < <(echo "$filename" | grep -Eo '\<201[5-8][0-9]{4}\>')
if [[ ${#dates[@]} -eq 2 ]] && [[ ${dates[0]} != ${dates[1]} ]]; then
destdir=$(dirname "$filename" | sed "s/${dates[0]}/${dates[1]}/")
mkdir -p "$destdir"
mv -v "$filename" "$destdir"
fi
done
测试:
$ tree
.
├── 20180621
│ └── a
│ └── b
│ ├── a.20180621.txt
│ └── foo.20180701.bar
└── 20180701
└── c
└── d
└── ok.20180701
6 directories, 3 files
我们有一个文件需要移动
$ find . -type f -print0 |
while IFS= read -d "" -r filename; do
mapfile -t dates < <(echo "$filename" | grep -Eo '\<201[5-8][0-9]{4}\>')
if [[ ${#dates[@]} -eq 2 ]] && [[ ${dates[0]} != ${dates[1]} ]]; then
destdir=$(dirname "$filename" | sed "s/${dates[0]}/${dates[1]}/")
mkdir -p "$destdir"
mv -v "$filename" "$destdir"
fi
done
'./20180621/a/b/foo.20180701.bar' -> './20180701/a/b/foo.20180701.bar'
结果
$ tree
.
├── 20180621
│ └── a
│ └── b
│ └── a.20180621.txt
└── 20180701
├── a
│ └── b
│ └── foo.20180701.bar
└── c
└── d
└── ok.20180701
8 directories, 3 files
不依赖 grep,这是对 Arount 回答的一个调整:
find 20+([0-9])/ -type f -print0 |
while IFS= read -d "" -r filename; do
dirdate=${filename%%/*}
if [[ "$(basename "$filename")" =~ 20[0-9]{6} ]]; then
filedate=${BASH_REMATCH[0]}
if [[ $dirdate != $filedate ]]; then
dest=${filename/$dirdate/$filedate}
echo mkdir -p "$(dirname "$dest")"
echo mv -v "$filename" "$dest"
fi
fi
done