Bash 根据文件名将文件移动到正确的日期目录
我的一些文件位于不正确的目录中,我正在尝试将它们移动到正确的位置 例如: 目录20180622将只包含名称中包含20180622的文件名 如果20180622目录包含名称为20180623的文件,则该文件是一个放错位置的文件,应转到相应的正确目录,即20180623 目录结构是固定的(幸运的是) 使用Bash 根据文件名将文件移动到正确的日期目录,bash,mv,Bash,Mv,我的一些文件位于不正确的目录中,我正在尝试将它们移动到正确的位置 例如: 目录20180622将只包含名称中包含20180622的文件名 如果20180622目录包含名称为20180623的文件,则该文件是一个放错位置的文件,应转到相应的正确目录,即20180623 目录结构是固定的(幸运的是) 使用查找-键入fi获取所有文件的列表,但不获取如何mv将文件放置到正确的位置。 someprefix可以是任何东西(它可能也包含一个点,所以cut不是从文件名中提取日期的好方法)$f=~(.*)(201
查找-键入f
i获取所有文件的列表,但不获取如何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
的同一路径
编辑评论
如果要为文件名处理多个delemiter,只需更改filedate=
行,如下所示:
filedate=$(basename $path | awk -F'[._\-]' '{print $2}' 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
我们有一个文件需要移动
$ 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'
不依赖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
someprefix
和somesuffix
是否始终相同?不幸的是,否:(,可以是任何文本,我只能保证始终包含日期,但是somesuffix始终以.gz
结尾。如果有解决方案,我可以为所有someprefix集运行多个命令。鉴于Python是您用户名的一部分,我建议使用它而不是Bash来解决此问题。这样更容易实现nt。您可以在这里学习如何操作bash参数:是的,这几乎可以工作,但是前缀和后缀可以有点。
或-
或-
作为septor,所以从文件名中剪切日期现在对我来说是个问题。我需要一个正则表达式,它可以为我提供文件名日期=$(echo$path | cut-d'/'-f 5)
现在假设我得到sometext\u date-sometext或dometext-date-sometext或sometext.date.sometext等,那么可以从上面提取模式201[5-8][0-9][0-9][0-9][0-9]的正则表达式将是理想的。日期一直是yyyyyymmdd格式,由两端的某物分隔[anything]yyyyyymmdd[anything]类似于$f=~(201[5-8][0-9][0-9][0-9][0-9][0-9])(.*)
但不确定,只是添加到这里作为我的尝试
$ 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
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