I have a bunch of directories that I need to restructure. They're in a format as such:

./1993-02-22 - The Moon - Tallahassee, FL/**files**
./1993-02-23 - The Moon - Tallahassee, FL/**files**
./1993-02-24 - The Moon - Tallahassee, FL/**files**
./1993-02-25 - The Moon - Tallahassee, FL/**files**
./1993-03-01 - The Test - Null, FL/**files**

I want to extract the dates from the beginning of each folder. For example, in regex: ([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2}) and reformat the directories to ./year/month/day.

So, it should output:

./1993/02/22/**files**
./1993/02/23/**files**
./1993/02/24/**files**
./1993/02/25/**files**
./1993/03/01/**files**

How can I go about doing that from a command line?

有帮助吗?

解决方案

I understood the question in a different way than Kent. I thought that you wanted to create a new tree of directories from each original one and move all files that it contained. You could try following script if that was what you were looking for:

perl -MFile::Path=make_path -MFile::Copy=move -e '
    for ( grep { -d } @ARGV ) {
        @date = m/\A(\d{4})-(\d{2})-(\d{2})/;
        next unless @date;
        $outdir = join q{/}, @date;
        make_path( $outdir );
        move( $_, $outdir );
    }
' *

It reads every file from current directory (* passed as argument) and does two step filter. The first one is the grep for no-directories files and the second one is an undefined @date for those that don't begin with it. Then it joins date's components into a path, creates it if doesn't exist and move the old one with all its files to the new one.

A test:

Here the result of ls -lR to show initial state:

.:
total 24
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:56 1993-02-22 - The Moon - Tallahassee, FL
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:56 1993-02-23 - The Moon - Tallahassee, FL
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:56 1993-02-24 - The Moon - Tallahassee, FL
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:57 1993-02-25 - The Moon - Tallahassee, FL
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:57 1993-03-01 - The Test - Null, FL
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:47 dummy_dir
-rw-r--r-- 1 dcg dcg    0 sep  7 00:47 dummy_file

./1993-02-22 - The Moon - Tallahassee, FL: 
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file1
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file2

./1993-02-23 - The Moon - Tallahassee, FL: 
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file3

./1993-02-24 - The Moon - Tallahassee, FL: 
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file4

./1993-02-25 - The Moon - Tallahassee, FL: 
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:57 file5
-rw-r--r-- 1 dcg dcg 0 sep  7 00:57 file6

./1993-03-01 - The Test - Null, FL: 
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:57 file7

./dummy_dir:
total 0

And after running the previous script note that the base directory only keeps dummy files and the root of the tree created (1993). Running the same ls -lR yields:

.:
total 8                                                                                                                                                                                                                                     
drwxr-xr-x 4 dcg dcg 4096 sep  7 00:59 1993                                                                                                                                                                                                 
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:47 dummy_dir                                                                                                                                                                                            
-rw-r--r-- 1 dcg dcg    0 sep  7 00:47 dummy_file                                                                                                                                                                                           

./1993:                                                                                                                                                                                                                                     
total 8                                                                                                                                                                                                                                     
drwxr-xr-x 6 dcg dcg 4096 sep  7 00:59 02
drwxr-xr-x 3 dcg dcg 4096 sep  7 00:59 03

./1993/02:
total 16
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:56 22
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:56 23
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:56 24
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:57 25

./1993/02/22:
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file1
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file2

./1993/02/23:
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file3

./1993/02/24:
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:56 file4

./1993/02/25:
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:57 file5
-rw-r--r-- 1 dcg dcg 0 sep  7 00:57 file6

./1993/03:
total 4
drwxr-xr-x 2 dcg dcg 4096 sep  7 00:57 01

./1993/03/01:
total 0
-rw-r--r-- 1 dcg dcg 0 sep  7 00:57 file7

./dummy_dir:
total 0

其他提示

Suppose your files are stored in "old" folder, then you may write a shell script (avoid using "for" loop that has difficulties with file names containing spaces):

mkdir -p new
ls -d -1 old/*/* | while read oldfile; do
    newfile=`echo "$oldfile" | sed -r 's#^old/([0-9]{4})\-([0-9]{1,2})\-([0-9]{1,2})(.*)$#new/\1/\2/\3/\4#'`
    newdir=` echo $newfile | sed 's#/[^/]*$##'`
    echo "Creating \"$newdir\""
    mkdir -p "$newdir"
    echo "Moving files from \"$oldfile\" to \"$newfile\""
    cp -r "$oldfile" "$newfile"
done

output of script:

Creating "new/1993/02/22/ - The Moon - Tallahassee, FL"
Moving files from "old/1993-02-22 - The Moon - Tallahassee, FL/test" to "new/1993/02/22/ - The Moon - Tallahassee, FL/test"
Creating "new/1993/02/23/ - The Moon - Tallahassee, FL"
Moving files from "old/1993-02-23 - The Moon - Tallahassee, FL/test" to "new/1993/02/23/ - The Moon - Tallahassee, FL/test"
Creating "new/1993/02/24/ - The Moon - Tallahassee, FL"
Moving files from "old/1993-02-24 - The Moon - Tallahassee, FL/test" to "new/1993/02/24/ - The Moon - Tallahassee, FL/test"
Creating "new/1993/02/25/ - The Moon - Tallahassee, FL"
Moving files from "old/1993-02-25 - The Moon - Tallahassee, FL/test" to "new/1993/02/25/ - The Moon - Tallahassee, FL/test"
Creating "new/1993/03/01/ - The Tes - Null, FL"
Moving files from "old/1993-03-01 - The Tes - Null, FL/test2" to "new/1993/03/01/ - The Tes - Null, FL/test2"

and you'll find your new tree in ... the "new" folder indeed:

$ tree old new
old
├── 1993-02-22 - The Moon - Tallahassee, FL
│   └── test
├── 1993-02-23 - The Moon - Tallahassee, FL
│   └── test
├── 1993-02-24 - The Moon - Tallahassee, FL
│   └── test
├── 1993-02-25 - The Moon - Tallahassee, FL
│   └── test
└── 1993-03-01 - The Tes - Null, FL
    └── test2
new
└── 1993
    ├── 02
    │   ├── 22
    │   │   └──  - The Moon - Tallahassee, FL
    │   │       └── test
    │   ├── 23
    │   │   └──  - The Moon - Tallahassee, FL
    │   │       └── test
    │   ├── 24
    │   │   └──  - The Moon - Tallahassee, FL
    │   │       └── test
    │   └── 25
    │       └──  - The Moon - Tallahassee, FL
    │           └── test
    └── 03
        └── 01
            └──  - The Tes - Null, FL
                └── test2

like this?

kent$  awk '{gsub(/-/,"/",$1);sub(/^[^/]*\//,"/",$NF);print $1$NF}' file
./1993/02/22/**files**
./1993/02/23/**files**
./1993/02/24/**files**
./1993/02/25/**files**
./1993/03/01/**files**

Here is a sed+awk after so much of comments :

awk 'BEGIN{FS="-"}{print $1"/"$2"/"$3}' file | awk 'BEGIN{FS="**files**"}{print $1"/"FS}' | sed -e 's/ \//\//g'

./1993/02/22/**files**
./1993/02/23/**files**
./1993/02/24/**files**
./1993/02/25/**files**
./1993/03/01/**files**
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top