Come sostituire una cartella il cui nome è una data, cioè AAAAMMGG con gerarchia di cartelle di anno, mese, data?

8

Ho una lista di cartelle che hanno date per i nomi. Le date sono nel formato AAAAMMGG (ad esempio 20150129). All'interno di queste cartelle ci sono documenti di testo relativi a quella data specifica.

Mi piacerebbe ristrutturarli in una gerarchia di cartelle che va di anno in mese, e spostare i documenti di testo nella corrispondente cartella "data" più in basso nella gerarchia.

In altre parole vorrei che la cartella 'root' fosse chiamata dopo l'anno come il 2015, quindi creare sottocartelle denominate con mesi come 01, quindi creare ulteriori sottocartelle denominate con date come 29 che contengono documenti di testo corrispondenti.

Quindi il percorso sarà simile a 2015/01/29/file.txt o 2015>01>29>file.txt .

Ho dato un'occhiata ad Automator e sembra che qualcosa del genere non sia possibile anche se potrei sbagliarmi, quindi mi piacerebbe sapere ...

  1. C'è qualche soluzione facile a questo problema che qualsiasi profano può capire, ad esempio un flusso di lavoro di Automator, o richiede una certa comprensione dei comandi del terminale e delle espressioni regolari?

  2. Come risolverebbe questo problema, a patto che ci sia effettivamente una soluzione?

posta davidjnatarajan 29.04.2017 - 17:22
fonte

2 risposte

8

Supponendo che tutte queste cartelle YYYYMMDD facciano parte della stessa directory principale che potresti eseguire

cd PARENT_DIRECTORY
for d in */; do
    [[ $d =~ [0-9]{8}/ ]] || continue
    mkdir -p -- "${d:0:4}/${d:4:2}"
    mv -- "$d" "${d:0:4}/${d:4:2}/${d:6:2}"
done
  • Il ciclo for d in */; do legge tutte le voci della directory, la percentuale finale di/ garantisce che solo i nomi delle directory corrispondano effettivamente
  • [[ $d =~ [0-9]{8}/ ]] verifica se la voce corrente è composta da 8 cifre e continua con la voce successiva se non
  • ${d:0:4}/${d:4:2}/${d:6:2} utilizza l'espansione dei parametri in bash per creare una stringa contenente il nuovo percorso
  • Il -- in mkdir e mv previene il problema nel caso in cui la directory o il nome del file inizi con - . Questo non può succedere qui, ma probabilmente è comunque una buona pratica.

Grazie a @terdon e @ user3439894 per idee su come migliorare lo script originale.

    
risposta data 29.04.2017 - 20:12
fonte
8

È possibile utilizzare quanto segue in Terminale. cd alla cartella contenente, quindi eseguire quanto segue:

find . -type f -exec bash -c \
  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})#//#" <<< $1);\
  mkdir -p -- $(dirname "$F");\
  mv -- "$1" "$F"' - {} \;

find . -type f ottiene ogni file nella directory corrente in modo ricorsivo.
-exec bash -c apre una shell per eseguire i seguenti comandi.
F=$(…) apre una subshell e usa sed sul percorso del file per manipolare il percorso nelle cartelle.
^\./([0-9]{4})([0-9]{2})([0-9]{2}) è un'espressione regolare con tre gruppi di cattura, come segue:
//èlasostituzione,incuiciascungruppodicattura(,ecc.)èseparatoda/.
mkdir-p--$(dirname"$F") crea le directory in cui spostare i file.
mv -- "$1" "$F" sposta ciascun file in la sua cartella corrispondente.

Questo assume la gerarchia a sinistra e la converte nella gerarchia a destra:

├── 20170201               └── 2017
│   └── abcdefghij             ├── 02
└── 20170302                   │   └── 01
    └── abcdefghij 2           │       └── abcdefghij
                               └── 03
                                   └── 02
                                       └── abcdefghij 2

Se nella cartella contenente ci sono altri file con una data come nome, questi verranno spostati come se fossero una cartella. Per evitare ciò, sostituire la seconda riga con:

  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})(?:/.+)#//#" <<< $1);\

Il (?:/.+) garantisce che il percorso abbia un componente successivo, quindi ignora qualsiasi cosa senza un figlio nella directory superiore che sono i file.

    
risposta data 29.04.2017 - 18:16
fonte

Leggi altre domande sui tag