Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 根据文件名将文件移动到正确的日期目录_Bash_Mv - Fatal编程技术网

Bash 根据文件名将文件移动到正确的日期目录

Bash 根据文件名将文件移动到正确的日期目录,bash,mv,Bash,Mv,我的一些文件位于不正确的目录中,我正在尝试将它们移动到正确的位置 例如: 目录20180622将只包含名称中包含20180622的文件名 如果20180622目录包含名称为20180623的文件,则该文件是一个放错位置的文件,应转到相应的正确目录,即20180623 目录结构是固定的(幸运的是) 使用查找-键入fi获取所有文件的列表,但不获取如何mv将文件放置到正确的位置。 someprefix可以是任何东西(它可能也包含一个点,所以cut不是从文件名中提取日期的好方法)$f=~(.*)(201

我的一些文件位于不正确的目录中,我正在尝试将它们移动到正确的位置

例如:

目录20180622将只包含名称中包含20180622的文件名

如果20180622目录包含名称为20180623的文件,则该文件是一个放错位置的文件,应转到相应的正确目录,即20180623 目录结构是固定的(幸运的是)

使用
查找-键入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