Adı olan bir klasörü nasıl değiştiririm? YYYYMMDD yıl, ay, tarih klasör hiyerarşisiyle nasıl değiştirilir?


8

Adlar için tarihleri ​​olan klasörlerin bir listesi var. Tarihler YYYYMMDD biçimindedir (örn. 20150129). Bu klasörler içinde, söz konusu tarihle ilgili metin belgeleri bulunur.

Bunları yıldan yıla bir klasör hiyerarşisinde yeniden yapılandırmak ve metin belgelerini hiyerarşide aşağıya karşılık gelen 'tarih' klasörüne taşımak istiyorum.

Başka bir deyişle, 'kök' klasörünün 2015 gibi bir yıl sonra adlandırılmasını ve sonra 01 gibi aylarla adlandırılmış alt klasörler oluşturmak ve sonra karşılık gelen metin belgelerini tutan 29 gibi tarihlerle adlandırılmış başka alt klasörler oluşturmak istiyorum .

Yani yol 2015/01/29/file.txtya benziyordu 2015>01>29>file.txt.

Automator'a bir göz attım ve yanlış olabilmeme rağmen böyle bir şey mümkün değil gibi görünüyor, bu yüzden bilmek istiyorum ...

  1. Bu problemin herhangi bir iş adamının anlayabileceği kolay bir çözümü var mı, örneğin bir Automator iş akışı mı, yoksa bu, terminal komutlarının ve düzenli ifadelerin biraz anlaşılmasını gerektiriyor mu?

  2. Aslında bir çözüm olması şartıyla bu problem nasıl çözülür?


Kim bu soruyu "çok geniş" olarak kapatmak için oy verdi, neden? Bu soru hakkında "çok geniş" olanı merak ediyorum.
user3439894

Bu YYYYMMDD klasörlerinin tümü doğrudan bir ana klasör içinde mi yoksa daha geniş bir hiyerarşiye yayılmış mı?
nohillside

@patrix Benim durumumda hepsi aynı dizinde veya ana klasörde
davidjnatarajan

Yanıtlar:


8

Tüm bu YYYYMMDD klasörlerinin çalıştırabileceğiniz aynı üst dizinin bir parçası olduğu varsayılarak

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
  • for d in */; doDöngü bütün dizin girişlerini okur sondaki /olmasını sağlar sadece dizin isimleri aslında eşleşmesini
  • [[ $d =~ [0-9]{8}/ ]] geçerli girişin 8 basamaktan oluşup oluşmadığını test eder ve değilse bir sonraki girişe devam eder
  • ${d:0:4}/${d:4:2}/${d:6:2}bashyeni yolu içeren bir dize oluşturmak için içindeki parametre genişletmeyi kullanır
  • Her --ikisinde de mkdirve mvdizin veya dosya adının bir ile başlaması durumunda sorunu önler -. Bu burada olamaz ama yine de muhtemelen iyi bir uygulamadır.

@Terdon ve @ user3439894'e orijinal betiğin nasıl geliştirileceğine dair fikirler için teşekkür ederiz.


Cevabınız için teşekkürler, bu mükemmel çalışıyor! Bu çözümün @grgarside tarafından sağlanan çözümden daha iyi olduğunu düşünüyorum, çünkü özellikle binlerce metin belgesi içeren devasa bir şirketle uğraşırken çok daha hızlı.
davidjnatarajan

8

Terminal'de aşağıdakileri kullanabilirsiniz. cdiçeren klasöre gidin, ardından aşağıdakileri çalıştırın:

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

find . -type fgeçerli dizindeki tüm dosyaları özyinelemeli olarak alır.
-exec bash -caşağıdaki komutları çalıştırmak için bir kabuk açar.
F=$(…)bir alt kabuk açar ve klasördeki yolu değiştirmek için dosya yolunda sed kullanır.
^\./([0-9]{4})([0-9]{2})([0-9]{2})aşağıdaki üç yakalama grubuna sahip bir normal ifadedir: her yakalama grubunun ( vb.) birbirinden ayrıldığı yedek . dosyaları taşımak için dizinleri oluşturur.
\1/\2/\3\1/
mkdir -p -- $(dirname "$F")
mv -- "$1" "$F"her dosyayı ilgili klasöre taşır.

Bu, soldaki hiyerarşiyi alır ve sağdaki hiyerarşiye dönüştürür:

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

İçeren klasörde tarih olarak ad olarak başka dosyalar varsa, bunlar bir klasörmiş gibi taşınır. Bunu önlemek için ikinci satırı değiştirin:

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

(?:/.+)Yolu bir sonraki bileşenine sahip olmasını sağlar, bu nedenle dosyalardır üst dizinde bir çocuk olmadan hiçbir şey yok sayarak.


@klanomath regex101.com
grg

@grgarside Thanx
klanomath
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.