按日期将文件排序到子文件夹中-bash

按日期将文件排序到子文件夹中-bash,bash,sorting,command-line,directory,command,Bash,Sorting,Command Line,Directory,Command,基本上我的硬盘崩溃了,我能够恢复所有的文件,但是,所有的文件都保留了它们的元数据&一些文件保留了它们的名字,我有274000个图像,我需要或多或少地按日期将它们分类到文件夹中 假设它从第一个文件开始,它将从文件中获取日期,创建一个子文件夹,直到日期更改,继续将该文件移动到创建的文件夹中,一旦日期更改,它将创建一个新文件夹并继续执行相同的操作 我相信这是可能的,我真的不想手动做这件事,因为这将需要几个星期 假设我有一个目标文件夹/目标/ 目标包含274000个文件,根本不在子文件夹中 文件夹结构应

基本上我的硬盘崩溃了,我能够恢复所有的文件,但是,所有的文件都保留了它们的元数据&一些文件保留了它们的名字,我有274000个图像,我需要或多或少地按日期将它们分类到文件夹中

假设它从第一个文件开始,它将从文件中获取日期,创建一个子文件夹,直到日期更改,继续将该文件移动到创建的文件夹中,一旦日期更改,它将创建一个新文件夹并继续执行相同的操作

我相信这是可能的,我真的不想手动做这件事,因为这将需要几个星期

假设我有一个目标文件夹/目标/

目标包含274000个文件,根本不在子文件夹中

文件夹结构应为/target/YY/DD_MM/文件名

我想为此创建一个bash脚本,但我真的不确定从哪里开始

我发现:

#!/bin/bash

DIR=/home/data
target=$DIR
cd "$DIR"

for file in *; do

    dname="$( date -d "${file%-*}" "+$target/%Y/%b_%m" )"
    mkdir -vp "${dname%/*}"
    mv -vt "$dname" "$file"

done
在不检查文件夹是否存在的情况下创建文件夹会删除该文件夹中的文件吗

我也不太确定向dir路径名添加asterix会做什么

我对bash不太熟悉,但如果有人能再给我解释一下到底发生了什么,我很想让它工作起来


谢谢

我似乎找到了一个适合我的答案,这在OSX上对三个文件都很有效,在我对大型文件夹运行它之前,你们能检查一下这不会在什么地方失败吗

#!/bin/bash

DIR=/Users/limeworks/Downloads/target
target=$DIR
cd "$DIR"

for file in *; do
    # Top tear folder name
    year=$(stat -f "%Sm" -t "%Y" $file)
    # Secondary folder name
    subfolderName=$(stat -f "%Sm" -t "%d-%m-%Y" $file)

    if [ ! -d "$target/$year" ]; then
        mkdir "$target/$year"
        echo "starting new year: $year"
    fi
    if [ ! -d "$target/$year/$subfolderName" ]; then
        mkdir "$target/$year/$subfolderName"
        echo "starting new day & month folder: $subfolderName"
    fi
    echo "moving file $file"
    mv "$file" "$target/$year/$subfolderName"

done

我编写了一个小脚本并进行了测试。希望这能有所帮助

#!/bin/bash
pwd=`pwd`
#list all files,cut date, remove duplicate, already sorted by ls.
dates=`ls  -l --time-style=long-iso|grep -e  '^-.*'|awk '{print $6}'|uniq`
#for loop to find all files modified on each unique date and copy them to your pwd
for date in $dates; do
    if [ ! -d "$date" ]; then
        mkdir "$date"
    fi
#find command will find all files modified  at particular dates and ignore hidden files.
    forward_date=`date -d  "$date + 1 day" +%F`
    find "$pwd" -maxdepth 1 -not -path '*/\.*' -type f  -newermt "$date" ! -newermt "$forward_date" -exec cp -f {} "$pwd/$date" \;
done

您必须在工作目录中,根据日期复制文件的位置

由于我的文件系统是远程安装的,访问时间很长,所以我对其他解决方案的性能也有问题

我在bash和python中开发了一些改进的解决方案:


Bash版本:

record # cat test.sh
for each in *.mkv
do
  date=$(date +%Y-%d-%m -r "$each");
  _DATES+=($date);
  FILES+=($each);
done

DATES=$(printf "%s\n" "${_DATES[@]}" | sort -u);
for date in ${DATES[@]}; do
  if [ ! -d "$date" ]; then
    mkdir "$date"
  fi
done

for i in  ${FILES[@]}; do
  dest=$(date +%Y-%d-%m -r "$i")
  mv $i $dest/$i
done

record # time bash test.sh
real    0m3.785s
record #

:


这两个脚本都在过去3天内修改的319个mkv文件上进行测试。

这些文件的名称中是否包含日期?给我们一个输入文件名称示例不全是不,我希望有一种方法可以从文件中获取日期,它self@sputnickIs
ls-ltr
显示文件的不同日期?在linux中,文件上通常不编码创建日期。您可以获取文件的访问日期和修改日期。您喜欢按哪一个日期排序?@Xorg我刚刚在这个帖子上发布了一个答案,您介意检查一下以确保我没有犯任何错误吗?我注意到“stat-f”%Sm“-t”%d-%m-%Y“$file”没有以人类可读的方式输出。我得到的示例如下“32ac003f03444607 255 ef53 4096 4096 16788382 12900871 12042299 4276224 39“对于每个文件。这样可以吗?你在用OSX吗?对我来说,它没有这样做:/@ShannonHochkins:你最终使用了什么?在这里的评论中,答案很好,但它在文件名和空格之间存在问题。如果没有空间,它可以进行排序,有了空间,它会将所有内容转储到目标foldermatt的根目录中-在我的OP中,我不需要或在文件路径中没有任何空间,这种逻辑可以为您扩展,并且与此OPOS无关您使用的是什么?我只是在一个包含80000个jpg文件的文件夹上尝试了python解决方案。它工作得很好,只花了11秒。
import os, datetime, errno, argparse, sys

def create_file_list(CWD):
    """ takes string as path, returns tuple(files,date) """

    files_with_mtime = []
    for filename in [f for f in os.listdir(CWD) if os.path.splitext(f)[1] in ext]:
        files_with_mtime.append((filename,datetime.datetime.fromtimestamp(os.stat(filename).st_mtime).strftime('%Y-%m-%d')))
    return files_with_mtime

def create_directories(files):
    """ takes tuple(file,date) from create_file_list() """

    m = []
    for i in files:
        m.append(i[1])
    for i in set(m):
        try:
            os.makedirs(os.path.join(CWD,i))
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                raise

def move_files_to_folders(files):
    """ gets tuple(file,date) from create_file_list() """
    for i in files:
        try:
            os.rename(os.path.join(CWD,i[0]), os.path.join(CWD,(i[1] + '/' + i[0])))
        except Exception as e:
            raise
    return len(files)


if __name__ == '__main__':

    parser = argparse.ArgumentParser(prog=sys.argv[0], usage='%(prog)s [options]')
    parser.add_argument("-e","--extension",action='append',help="File extensions to match",required=True)
    args = parser.parse_args()

    ext =  ['.' + e for e in args.extension]
    print "Moving files with extensions:", ext
    CWD = os.getcwd()
    files = create_file_list(CWD)
    create_directories(files)
    print "Moved %i files" % move_files_to_folders(files)

record # time python sort.py -e mkv
Moving files with extensions: ['.mkv']
Moved 319 files
real    0m1.543s
record #