Skopiuj grupę plików (Nazwa pliku *) do kopii zapasowej (Nazwa pliku * .bak)

12

tło

W systemie Linux możesz:

  • Wyświetl grupę plików za pomocą ls Filename*
  • Usuń grupę plików za pomocą rm Filename*
  • Przenieś grupę plików za pomocą mv Filename* /New/Directory
  • Ale nie można skopiować grupy plików za pomocą:cp Filename* *.bak

Zmień cpkomendę Linux, aby skopiować grupę plików

Mam grupę plików, które chciałbym skopiować bez wprowadzania nazw jeden po drugim i używania cppolecenia:

$ ls gmail-meta3*
gmail-meta3                          gmail-meta3-REC-1558392194-26467821
gmail-meta3-LAB-1558392194-26467821  gmail-meta3-YAD-1558392194-26467821

Jak mogę użyć czegoś takiego jak stare polecenie DOS copy gmail-meta3* *.bak?

Nie chcę wpisywać podobnego polecenia cztery razy:

cp gmail-meta3-LAB-1558392194-26467821 gmail-meta3-LAB-1558392194-26467821.bak

Szukam skryptu / funkcji / aplikacji, która akceptuje parametry dla starej i nowej grupy nazw plików, a nie coś z zakodowanymi nazwami plików. Na przykład użytkownik może wpisać:

copy gmail-meta3* *.bak

lub mogą wpisać:

copy gmail-meta3* save-*
WinEunuuchs2Unix
źródło
1
Wydaje mi się, że problem polega na dwukrotnym użyciu operatora glob, z którego nie korzysta żadne inne polecenie. bash nie jest wystarczająco inteligentny, aby sobie z tym poradzić.
qwr
2
@qwr, fakt, że bash rozszerza metaznaki i tokenizuje dane wejściowe przed przekazaniem ich do polecenia do wykonania, jest częścią projektu powłok UNIX. Aby jakoś spróbować zaprogramować wyjątek dla polecenia cp, złamałby całą spójność bash, co wcale nie byłoby mądre. W ramach ćwiczenia spróbuj dowiedzieć się, co się tutaj dzieje i dlaczego jest to rozszerzenie metaznaków powłoki, które sprawia, że ​​tak:touch aa ab ba; mkdir bb; cp a* b*; ls *
Mike S
@MikeS Dzięki za wskazówki. Wczoraj ktoś inny powiedział, że możesz użyć znaku wieloznacznego *dla nazw plików źródłowych, ale nie dla nazw plików docelowych. Jako taki, jak zastępczy symbol zastępczy (myślę, że ##został zasugerowany, ale pochylam się w kierunku %), będzie musiał zostać użyty jako cel. Myślę, że to właśnie wzmacniasz? Nie spodziewałem się cpw ogóle zmienić polecenia. Wystarczy utworzyć skrypt otoki, copyktóry naśladuje (w granicach rozsądku) polecenie kopiowania DOS.
WinEunuuchs2Unix
@ WinEunuuchs2Unix ta osoba była poprawna. Metaznaki powłoki są niezależne od poleceń. Dlatego wszystkie symbole wieloznaczne będą próbować dopasować wszystkie pliki pasujące do wzorca. Jeśli próbujesz dopasować uniwersalny program „dopasuj wszystko i skopiuj go do tego, czym były, ale dodaj ten sufiks”, to tak, umieszczenie nieoznaczonego metaznaku, ponieważ cel prawdopodobnie nie zrobi tego, co chcesz. Ponieważ wszystkie metaznaki w wierszu poleceń powłoki są rozwinięte. Jeśli WIESZ na pewno, że metaznak docelowy nigdy nie będzie pasował, możesz go użyć - ponieważ powłoka nie może go rozwinąć.
Mike S
... ale to byłoby brzydkie. Lepiej użyć specjalnej postaci. % lub podkreślenie są dobre, na ogół nie są metaznakami (ale uważaj na użycie% w pliku crontab; jest tam wyjątkowy).
Mike S

Odpowiedzi:

13

Oto przykład jednego nietypowego użycia sed, które ma zastosowanie do tego zadania:

sed -i.bak '' file-prefix*

W ten sposób faktycznie sednie zmieni plików, ponieważ nie dostarczyliśmy żadnych poleceń '', ale dzięki opcji -i[suffix]utworzy kopię zapasową każdego pliku. Znalazłem to podejście, kiedy szukałem. Czy istnieje sposób na utworzenie kopii zapasowej pliku, bez dwukrotnego wpisania jego nazwy?

pa4080
źródło
FYI: $ time sed -i.bak '' gmail-meta3*=real 0m0.069s
WinEunuuchs2Unix
Jeśli pliki już istnieje wówczas: real 0m0.037s. Jeśli pliki usunięte i uruchomić po raz drugi blisko cpprędkości: real 0m0.051s.
WinEunuuchs2Unix
@xiota Interesujący punkt. Okazuje się, że sedjest szybszy, gdy pliki docelowe już istnieją, ale cpjest wolniejszy, gdy istnieją pliki docelowe. Właściwie opróżniam pamięć podręczną i bufory, a nie syncrobię duże testy czasowe, ale tym razem nie zrobiłem tego. Ponieważ może to zagłębić się w zupełnie inną mydlaną operę bez pytania, z przykrością udostępniam wyniki moich testów :( Czy jest już za późno, by udawać, że ta rozmowa nigdy się nie wydarzyła? Rozmiar metadanych wiadomości Gmaila wynosi 2,5 MB, a 3 pliki indeksu mają około 800 KB Ponadto nie jest to dysk twardy, to dysk SSD Samsung Pro 960 NVMe na 4 kanałach
WinEunuuchs2Unix
1
Prawdopodobnie nie ma znaczenia, jakie masz urządzenie pamięci masowej do tych testów, jeśli dzieje się to na komputerze z systemem Linux. Jądro jest wyjątkowo dobre w buforowaniu plików w pamięci. Taka jest wartość „buff / cache” podczas używania freepolecenia. Rzeczywiste zapisy w urządzeniu mają miejsce w momencie wybranym przez algorytm, który uwzględnia wiek pamięci podręcznej i nacisk pamięci na maszynie. Jeśli próbujesz wykonać wiele testów, to pierwsze odczyty plików wyjdą z dysku, ale kolejne odczyty najprawdopodobniej wyjdą z pamięci (patrz sync; echo 3 > /proc/sys/vm/drop_caches).
Mike S
Wczoraj wykonałem kilka testów z dużymi plikami powyżej 2 GB i - tak, to podejście jest stosunkowo wolne niż użycie cppolecenia, ale nie mogę powiedzieć, że istnieje znacząca różnica w wydajności .
pa4080
12

Możesz użyć find:

find . -max-depth 1 -name 'gmail-meta3*' -exec cp "{}" "{}.bak" \;

To znajdzie w bieżącym katalogu .wszystkie pliki o nazwie pasującej do wzorca globu (pamiętaj o pojedynczych cudzysłowach wokół wzorca, aby zapobiec globowaniu powłoki). Dla każdego znalezionego pliku będzie on wykonywany cpod nazwy do nazwy.bak. \; na końcu zapewnia, że ​​zrobi każdy plik osobno, zamiast przekazywać je wszystkie naraz. Maksymalna głębokość, ponieważ 1 przeszukuje katalog cuurent zamiast rekurencji w dół.

Cbojar
źródło
1
Czy to zadziała, find . -max-depth 1 -name '"$1"'' -exec cp "{}" "{}$2" \;gdy 1 USD to źródło, a 2 USD to rozszerzenie?
WinEunuuchs2Unix
2 dolary powinny być w porządku, o ile jest to uzasadnione. 1 USD może być trudniejszy, ponieważ nie możemy zastępować zmiennych w pojedynczych cudzysłowach. Nie jestem pewien, czy to możliwe, ale może być możliwe użycie 1 $ w cudzysłowach, ponieważ wzór jest przechowywany w ciągu.
cbojar
11

Możesz użyć forpętli zbash . Zwykle po prostu wpisałbym go jako linijkę, ponieważ nie jest to zadanie, które często wykonuję:

for f in test* ; do cp -a "$f" "prefix-${f}.ext" ; done

Jeśli jednak potrzebujesz go jako skryptu:

cps() {
   [ $# -lt 2 ] && echo "Usage: cps REGEXP FILES..." && return 1

   PATTERN="$1" ; shift

   for file in "$@" ; do
      file_dirname=`dirname "$file"`
      file_name=`basename "$file"`
      file_newname=`echo "$file_name" | sed "$PATTERN"`

      if [[ -f "$file" ]] && [[ ! -e "${file_dirname}/${file_newname}" ]] ; then
         cp -a "$file" "${file_dirname}/${file_newname}"
      else
         echo "Error: $file -> ${file_dirname}/${file_newname}"
      fi
   done
}

Użycie jest podobne do rename. Testować:

pushd /tmp
mkdir tmp2
touch tmp2/test{001..100}     # create test files
ls tmp2
cps 's@^@prefix-@ ; s@[email protected]@' tmp2/test*    # create backups
cps 's@[email protected]@' tmp2/test*    # more backups ... will display errors
ls tmp2
\rm -r tmp2                   # cleanup
popd
Xiota
źródło
FYI: $ time for f in gmail-meta3* ; do cp -a "$f" "${f}.bak" ; done=real 0m0.046s
WinEunuuchs2Unix
Nie, nie chcę optymalizować czasu. Są 0.046sekundy, co oznacza 0 sekund dla ludzkiej percepcji. Próbowałem tylko pokazać, w jaki sposób testuję opublikowane odpowiedzi i przekazuję ciekawe ciekawostki widzom, którzy spojrzeli na sedpowyższe polecenie. Albo przynajmniej nie był zainteresowany w porównaniu seddo cp....
WinEunuuchs2Unix
Twoje rozwiązanie z cpjest jednak szybsze niż rozwiązanie z sed. To jest powód do świętowania :)
WinEunuuchs2Unix
(1)  -ajest niestandardowym operatorem testowym. Dlaczego nie użyć -e? (2) „Nie można utworzyć katalogu tymczasowego.” Jest nieco mylącym komunikatem o błędzie. (3) Dlaczego nie po prostu użyć mktemp -d? (4) Powinieneś przetestować status wyjścia. Na przykład powinieneś powiedzieć ! mkdir "$FOLDER" && echo "Unable to create temporary directory." && return 1 lub  mkdir "$FOLDER" || { echo "Unable to create temporary directory."; return 1;}. Podobnie dla cpi  rename(a może nawet pushd, jeśli chcesz być ostrożny). … (Ciąg dalszy)
G-Man
(Ciąg dalszy)… (5) Arrggghhhh! Nie mów $@; powiedzieć "$@". (5b)  Nie ma potrzeby używania, {a } kiedy odwołujesz się do zmiennych, tak jak robisz ( "${FOLDER}",  "${PATTERN}" i  "${file}"); po prostu zrobić "$FOLDER",  "$PATTERN" i  "$file". (6) Zakłada się, że pliki znajdują się w bieżącym katalogu.  cps 's/$/.bak/' d/fooskopiuje d/foodo foo.bak bieżącego katalogu, a nie d/foo.bak.
G-Man
6

Najbliżej prawdopodobnie dostaniesz się do paradygmatu DOS mcp(z mmvpakietu):

mcp 'gmail-meta3*' 'gmail-meta3#1.bak'

Jeśli zshjest dostępny, to jego zmvmoduł może być nieco bliżej:

autoload -U zmv

zmv -C '(gmail-meta3*)' '$1.bak'

Unikałbym lsniezależnie - wariant na własną odpowiedź, który jest bezpieczny dla białych znaków (w tym nowych linii)

printf '%s\0' gmail-meta3* | while IFS= read -r -d '' f; do cp -a -- "$f" "$f.bak"; done

a może

printf '%s\0' gmail-meta3* | xargs -0 -I{} cp -a -- {} {}.bak
steeldriver
źródło
Rozumiem, że mmvto pakiet, ale w komentarzach mówisz, że polecenie jest, mcpale potem w poleceniu, którego używasz, mmvktóre jest również poleceniem w mmvpakiecie. Podoba mi się kierunek printfprzykładów i w dopracowanym skrypcie zapewniłbym przekazanie 1 $ i 2 $. +1 za rozpoczęcie toczenia piłki :)
WinEunuuchs2Unix
@ WinEunuuchs2Unix przeprosiny - mcp / mmv było fartem mózgowym. W rzeczywistości mcpjest tylko synonimemmmv -c
steeldriver
Pfft nie martw się. Gdybym miał dolara za każdą literówkę, którą napisałem, byłbym milionerem :) Chciałbym wyjaśnienia na printfpolecenie, którego tak naprawdę nigdy nie użyłem. Czy mówisz, printf '%s\0' "$1"*że działałoby, gdyby gmail-meta3został przekazany jako parametr 1?
WinEunuuchs2Unix
@ WinEunuuchs2Unix Prawdopodobnie pozwoliłbym kontekstowi wywołującemu wykonać globbing, cps gmail-meta3*a następnie napisałem printf '%s\0„$ @” | podczas gdy ... w funkcji. Lub po prostu użyj for f; do cp -- "$f" "$f.bak"; done(jak odpowiedź Xiota , ale jako funkcja)
steeldriver
1
Zauważ, zmvże możesz użyć trybu „zastępowania symboli wieloznacznych”, co zmv -W -C 'gmail-meta3*' '*.bak'
wydaje
5

tylko rozwiązanie rsync

Jeśli chcesz tylko wykonać kopię zapasową plików, możesz skopiować je do nowego katalogu

rsync /path/to/dir/Filename* /path/to/backupdirectory

Spowoduje to skopiowanie Filenameplików z /path/to/dir/do /path/to/backupdirectory.


rsync + nazwa pliku

Jeśli chcesz, aby pliki kopii zapasowych miały sufiks, rzeczy stają się hacked z rsync...

rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak

Spowodowałoby to zastąpienie istniejących plików ... istniejącymi plikami ( -I), ale tylko wtedy, gdy są ( -u) nowsze (które nie są) i utworzenie kopii zapasowej z przyrostkiem.

Możesz to również zrobić w tym samym katalogu. Lepiej jednak wyklucz istniejące kopie zapasowe.

rsync -Iu /path/to/dir/Filename* /path/to/dir/Filename* -b --backup-dir=/path/to/backupdirectory --suffix=.bak --exclude '*.bak'

Robert Riedl
źródło
Uwielbiam, rsycncwięc głosowałem, ale prostszą metodą byłoby, cp Filename* /path/to/backup/dirponieważ pliki nie potrzebowałyby *.bakunikalizatora, gdyby znajdowały się w osobnym katalogu.
WinEunuuchs2Unix
4

Ten należy wykonać zgodnie z żądaniem:

cps(){ p="${@: -1}"; for f in "${@:1:$#-1}"; do cp -ai "$f" "${p//\?/$f}"; done  }

Stosowanie:

cps FILES... pattern
Example 1: cps gmail-meta3* ?.bak
Example 2: cps * save-?
Example 3: cps * bla-?-blubb

Wybrałem, ?ponieważ #musi być cytowany, gdy jest to pierwszy znak wzoru, w przeciwnym razie zostanie rozpoznany jako początek komentarza.

Test:

$ touch 'test};{bla#?"blubb'
$ cps test* bla-?-blubb
$ ls
test};{bla#?"blubb  bla-test};{bla#?"blubb-blubb


Niektóre wcześniejsze wersje skryptu do dodawania sufiksu:

Podobne do odpowiedzi @ WinEunuuchs2Unix, ale myślę, że jest bardziej elastyczny i nie analizujels :

cps(){ S="$1"; shift; printf '%s\0' "$@" | xargs -0 -I{} cp -abfS "$S" {} {}; }

Umieść to w swoim .bashrc.

Stosowanie:

cps SUFFIX FILES...
Example: cps .bak gmail-meta3*

Alternatywnie, z sufiksem jako ostatnim argumentem ( via i via ):

cps(){ S="${@: -1}"; printf '%s\0' "${@:1:$#-1}" | xargs -0 -I{} cp -abfS "$S" {} {}; }

Stosowanie:

cps FILES... SUFFIX
Example: cps gmail-meta3* .bak

pLumo
źródło
Ładne kodowanie, ale po dziesięcioleciach używania Source, a następnie Target trudno jest zmienić polecenie kopiowania na Target, a następnie Source
WinEunuuchs2Unix
Dodano funkcję z przyrostkiem z tyłu.
pLumo
Dzięki temu jest bardziej intuicyjny. Nazwanie go sufiksem jest dokładne w sposób, w jaki kodowała go moja odpowiedź, ale tak naprawdę jest to cel lub miejsce docelowe. Inni użytkownicy mogą chcieć użyć: copy gmail-meta3* old-meta3*. W mojej odpowiedzi nie mogłem wymyślić, jak dostać *się do nazwy docelowej, tak jak moje pytanie ...
WinEunuuchs2Unix
Problem polega na tym, że *jest interpretowany przez powłokę, więc funkcja nie będzie o tym wiedzieć. Potrzebujesz innego znaku lub go zacytujesz, a następnie zastąp go oryginalną nazwą pliku w funkcji.
pLumo
Sądzę, że #można go użyć jako zamiennika wieloznacznego dla *? Więc możesz pisać copy filenames# save-#. Myślę, że chcesz, aby znak wieloznaczny był taki sam dla źródła i celu.
WinEunuuchs2Unix
4

Napisałem ten linijkę do siebie ~/.bashrc. findPrzypuszczam, że można opublikować znacznie lepsze odpowiedzi przy użyciu . Jeszcze lepsze odpowiedzi można napisać w C. Mam nadzieję, że te pytania i odpowiedzi sprawią, że otrzymamy lepsze odpowiedzi:

cps () {
    # cps "Copy Splat", copy group of files to backup, ie "cps Filename .bak"
    # Copies Filename1 to Filename1.bak, Filename2 to Filename2.bak, etc.
    # If Filename1.bak exists, don't copy it to Filename1.bak.bak
    for f in "$1"*; do [[ ! "$f" == *"$2" ]] && cp -a "$f" "$f$2"; done

    # OLD version comments suggested to remove 
    # ls "$1"* | while read varname; do cp -a "$varname" "$varname$2"; done
}
  • for f in "$1"*; do: $1to gmail-meta3parametr i flista pasujących plików. W połączeniu oznacza to dla gmail-meta3, gmail-meta3-LAB-9999 itp. Wykonaj następujące czynności
  • [[ ! "$f" == *"$2" ]] &&: $fjest taki sam jak fpowyżej. $2to .bakparametr przekazany. W połączeniu oznacza to, że jeśli nazwa pliku nie kończy się na .bak(ponieważ nie chcemy kopiować .baki tworzyć .bak.bak), wykonaj następujące czynności
  • cp -a "$f" "$f$2"; skopiuj gmail-meta3 na gmail-meta3.bak itp.
  • done: zapętlić i pobrać następną nazwę pliku z gmail-meta3listy *.

cps gmail-meta3 .bak Przykładowe dane wyjściowe

Przykładem tego pytania jest to, jak wygląda on w działaniu:

───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ ll gmail-meta3*
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821
-rw-rw-r-- 1 rick rick   728954 Jun 27 05:46 gmail-meta3-YAD-1558392194-26467821.bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ cps gmail-meta3 .bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ ll gmail-meta3*
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3
-rw-rw-r-- 1 rick rick 26467821 May 20 16:43 gmail-meta3.bak
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821
-rw-rw-r-- 1 rick rick      643 May 20 16:43 gmail-meta3-LAB-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821
-rw-rw-r-- 1 rick rick    49607 May 20 16:44 gmail-meta3-REC-1558392194-26467821.bak
-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821
-rw-rw-r-- 1 rick rick   728954 Jun 27 17:04 gmail-meta3-YAD-1558392194-26467821.bak
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/gmail$ 

Uwaga: Używa -aflagi z cppoleceniem, aby zachować znaczniki czasu i lepiej zrozumieć kopie zapasowe plików.

Zwróć uwagę, że kopie plików mają dokładnie tę samą datę i godzinę co oryginały. Jeśli -aparametr zostanie pominięty, otrzymają aktualną datę i godzinę i nie wyglądają jak prawdziwa kopia zapasowa, z wyjątkiem tego, że rozmiar pliku byłby taki sam.

WinEunuuchs2Unix
źródło
6
nie zawsze ludzie nie zalecają parsowanials
qwr
3
Od findkiedy wspomniałeś , zakładam, że zdajesz sobie sprawę z niebezpieczeństwa parsowania ls? Ale w twoim przypadku nie jest to konieczne: po prostu zrób for file in "$1"*; do copy -a "$file" "$file$2"; doneto - jest to całkowicie bezpieczne i znacznie prostsze niż jakikolwiek rodzaj pośrednictwa za pośrednictwem lslub findi whilepętli.
Konrad Rudolph
@KonradRudolph Dzięki za sugestię. Wdrożyłem i przetestowałem twoją sugestię z kilkoma drobnymi zmianami.
WinEunuuchs2Unix
2

Inną metodą spełnienia wymagań jest skopiowanie plików do katalogu tymczasowego i renamezmiana nazwy za pomocą polecenia.

$ mkdir backup
$ cp filename* /tmp/rename-backup/
$ rename 's/(filename.*)/$1.bak/' /tmp/rename-backup/*
$ mv /tmp/rename-backup/* ./

Jeśli potrzebujesz go jako skryptu, możesz go użyć w ten sposób

cps () {
    mkdir -p /tmp/rename-backup/
    cp "$1"* /tmp/rename-backup/
    rename "s/($1.*)/\$1.$2/" /tmp/rename-backup/*
    mv "/tmp/rename-backup/$1"*".$2" .
}

Możesz go używać w następujący sposób:

cps file bak

To jest przykład

$ ls -l
total 0
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file a
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ab
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ac
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename1
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename2
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename3
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename4
$ cps file bak
$ ls -l
total 0
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file a
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 file a.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ab
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 file ab.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:23 file ac
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 file ac.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename1
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 filename1.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename2
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 filename2.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename3
-rw-r--r--  1 danny  wheel  0 Jun 26 16:41 filename3.bak
-rw-r--r--  1 danny  danny  0 Jun 26 16:05 filename4
-rw-r--r--  1 danny  danny  0 Jun 26 16:41 filename4.bak
Dan
źródło