2013-01-24 12 views
10

Moja struktura katalogów jest następującaznaleźć pierwszy plik w katalogu

Directory1\file1.jpg 
      \file2.jpg 
      \file3.jpg 

Directory2\anotherfile1.jpg 
      \anotherfile2.jpg 
      \anotherfile3.jpg 

Directory3\yetanotherfile1.jpg 
      \yetanotherfile2.jpg 
      \yetanotherfile3.jpg 

próbuję użyć wiersza polecenia w powłoce bash na Ubuntu zrobić pierwszy plik z każdego katalogu i zmień jego nazwę do nazwy katalogu i przesuń go o jeden poziom wyżej, aby znalazł się obok katalogu.

W powyższym przykładzie:

  • file1.jpg zostanie zmieniona na Directory1.jpg i umieszczone obok folderu Directory1

  • anotherfile1.jpg zostanie zmieniona na Directory2.jpg i umieszczone obok katalogu katalog2

  • yetanotherfile1.jpg zostanie zmieniona na Directory3.jpg i umieszczona obok Folder e Directory3

Próbowałem przy użyciu:

find . -name "*.jpg" 

ale nie listę plików w kolejności (muszę pierwszy plik).

Linia:

find . -name "*.jpg" -type f -exec ls "{}" +; 

wymienia pliki w odpowiedniej kolejności, ale jak mam wybrać tylko pierwszy plik w każdym katalogu i przenieść go w górę o jeden poziom?

Każda pomoc zostanie doceniona!

Edycja: Kiedy odnosimy się do pierwszego pliku, mam na myśli to, że każdy jpg jest ponumerowany od 0 do jak największej liczby plików w tym folderze - na przykład: plik1, plik2 ...... plik34, plik35 itd ... Inną rzeczą, o której warto wspomnieć, jest format plików losowych, więc numeracja może rozpoczynać się od 0 lub 1a lub 1b itd.

+1

Zdefiniuj " pierwszy". –

+0

Rozszerzając komentarz Ignacio, ważne jest, aby wiedzieć, co masz na myśli przez "pierwszy". Pierwszy alfabetycznie? Jeśli tak i jeśli liczby mają 2 cyfry, czy chcesz posortować file3.jpg przed plikiem file10.jpg zamiast alfabetycznego sposobu, w którym plik 10.jpg byłby pierwszy? Jeśli nie chcesz alfabetycznie, czy chcesz pierwszy w kolejności sposób ich przechowywania na dysku? Według daty? I tak dalej. – Bdoserror

Odpowiedz

20

Jeśli pierwsza oznacza to, co skorupa globu znajdzie pierwsza (leksykalna, ale prawdopodobnie dotknięta przez LC_COLLATE), to powinno działać:

for dir in */; do 
    for file in "$dir"*.jpg; do 
     echo mv "$file" "${file%/*}.jpg" # If it does what you want, remove the echo 
     break 1 
    done 
done 

proof of concept:

$ mkdir dir{1,2,3} && touch dir{1,2,3}/file{1,2,3}.jpg 
$ for dir in */; do for file in "$dir"*.jpg; do echo mv "$file" "${file%/*}.jpg"; break 1; done; done 
mv dir1/file1.jpg dir1.jpg 
mv dir2/file1.jpg dir2.jpg 
mv dir3/file1.jpg dir3.jpg 
+0

Dokładnie to, czego potrzebuję - dzięki! – user2008746

1

Look dla wszystkich katalogów pierwszym poziomie zidentyfikować pierwszy plik w tym katalogu, a następnie przenieść go o jeden poziom w górę

find . -type d \! -name . -prune | while read d; do 
    f=$(ls $d | head -1) 
    mv $d/$f . 
done 
16

Można pójść wewnątrz każdego katalogu i uruchomić:

$ mv `ls | head -n 1` .. 
+0

prosty i Unixy, lubię – Cyril

+0

@Cyril [jest to zły pomysł, aby rury 'ls' jak ta] (https://unix.stackexchange.com/q/128985/44425) –

+0

Hi @ LưuVĩnhPhúc, dzięki za link. Artykuł sprawia, że ​​dobry punkt. W moim przypadku jednak nazwy plików były generowane automatycznie i po bardzo specyficzny predefiniowany format. Więc przypadki brzegowe artykuł ostrzega o naprawdę nie stosuje się. W przypadku ogólnym, tak, prawdopodobnie nie jest dobrym pomysłem. Dzięki! – Cyril