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

时间:2014-12-14 22:50:31

标签: bash sorting command-line directory command

基本上我的硬盘崩溃了,我能够恢复所有文件,但是,所有的文件都保留了他们的元和文件。有些人保留了他们的名字,我有274000张图片,我需要或多或少,按日期排序到文件夹中。

所以,让我们说它从第一个文件开始,它将从文件中获取日期,创建一个子文件夹,直到日期更改,一旦日期更改,继续将该文件移动到创建的文件夹中,它会创建一个新的文件夹并继续做同样的事情。

我确定这是可能的,我真的不想手动这样做,因为这需要几个星期......

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

目标包含274000个文件,根本没有子文件夹。

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

我想为此创建一个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不太熟悉,但如果有人可以向我解释一下发生了什么事情,我很乐意让这个工作起作用吗?

三江源!

3 个答案:

答案 0 :(得分:3)

我似乎找到了一个适合我的答案,这个在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

答案 1 :(得分:2)

我的其他解决方案的性能存在问题,因为我的文件系统是远程挂载的,访问时间很长。

我在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 #

Python version

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 #

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

答案 2 :(得分:1)

我在一个小脚本上工作并测试过它。希望这有帮助。

#!/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

您必须在工作目录中,根据日期存在要复制的文件。