find do dvou souborů

find do dvou souborů
« kdy: 27. 04. 2023, 22:17:47 »
Zdravím,
dotaz na bash. Jak se dá výstup z find poslat do dvou souborů? Hledám soubory v určitém rozsahu velikosti např 10-20MB a v jednom souboru chci mít jen názvy souborů a v druhém velikost souboru a název a na konci seznamu součet, kolik zabírají dohromady všechny nalezené soubory. Umím jen vypsat nalezené soubory do jednoho souboru ale ne do dvou souborů současně natož to sečíst.


Re:find do dvou souborů
« Odpověď #1 kdy: 27. 04. 2023, 22:33:18 »
Je mi to trochu trapný, ale

Můžete použít tento bash skript pro splnění vašich požadavků. Skript nejprve najde soubory o velikosti 10-20MB, a poté vytvoří dva soubory - jeden s názvy souborů a druhý s velikostí a názvy souborů. Na konci skriptu se spočítá celková velikost nalezených souborů a přidá se na konec druhého souboru.

```bash
#!/bin/bash

# Nastavte cestu, kde chcete hledat soubory
SEARCH_DIR="/cesta/k/hledani"

# Nastavte názvy výstupních souborů
FILENAMES_OUTPUT="nazvy_souboru.txt"
SIZES_AND_FILENAMES_OUTPUT="velikosti_a_nazvy_souboru.txt"

# Odstraňte existující výstupní soubory
rm -f "$FILENAMES_OUTPUT" "$SIZES_AND_FILENAMES_OUTPUT"

# Najděte soubory s velikostí mezi 10 a 20 MB
find "$SEARCH_DIR" -type f -size +10M -size -20M -print0 | while IFS= read -r -d '' file; do
  # Získejte název souboru
  filename=$(basename "$file")

  # Získejte velikost souboru v bytech
  size=$(stat -c "%s" "$file")

  # Přidejte název souboru do prvního souboru
  echo "$filename" >> "$FILENAMES_OUTPUT"

  # Přidejte velikost a název souboru do druhého souboru
  echo "$size $filename" >> "$SIZES_AND_FILENAMES_OUTPUT"
done

# Sečtěte celkovou velikost nalezených souborů a přidejte ji na konec druhého souboru
total_size=$(awk '{ sum += $1 } END { print sum }' "$SIZES_AND_FILENAMES_OUTPUT")
echo "Celkova velikost: $total_size" >> "$SIZES_AND_FILENAMES_OUTPUT"
```

Upravte `SEARCH_DIR` na cestu, kde chcete hledat soubory. Poté spusťte tento skript v příkazovém řádku. Výsledkem budou dva soubory: `nazvy_souboru.txt` obsahující pouze názvy nalezených souborů a `velikosti_a_nazvy_souboru.txt` obsahující velikosti a názvy nalezených souborů s celkovou velikostí na konci.

z_sk

Re:find do dvou souborů
« Odpověď #2 kdy: 27. 04. 2023, 22:37:27 »
Citace
Jak se dá výstup z find poslat do dvou souborů?
Kód: [Vybrat]
find | tee /dev/shm/log.1 > /dev/shm/log.2

Re:find do dvou souborů
« Odpověď #3 kdy: 27. 04. 2023, 22:56:53 »
Díky moc, registrovany_ava, to je velmi obohacující.
Mohu jeste polozit dotaz? Asi uplne nechapu ten kod, ale napisu co se mi honi v hlave na prvni pohled jako zacatecnikovi....

IFS= tam je mezera? Standardne byva tab x09 ? Nejsem si jisty proc to tam je.

$1 to je primo odkaz na prvni sloupec? Nevsiml jsem si kde se tato promenna nastavuje. Myslel jsem si ze by tam pod awk melo byt sum+-$size ... Nebo spis jsem ocekaval, ze se to secte uvnitr te smycky while ; do ... done; ze by se pak to awk nemuselo provadet?

Wolda

  • **
  • 79
  • http://honza.ucw.cz
    • Zobrazit profil
    • E-mail
Re:find do dvou souborů
« Odpověď #4 kdy: 28. 04. 2023, 00:06:17 »
Me teoreticke ja: asymptoticky je jak scitat prubezne uvnitr while smycky tak scitat na konci awk-ckem stejne rychle.

Me prakticke ja: scital bych rovnou uvnitr smycky. Jen nezapomente, ze ta smycka bezi v subshellu, takze dostat z ni vysledek vyzaduje drobnou ekvilibristiku.


k3dAR

  • *****
  • 3 071
  • porad nemam telo, ale uz mam hlavu... nobody
    • Zobrazit profil
    • E-mail
Re:find do dvou souborů
« Odpověď #5 kdy: 28. 04. 2023, 00:06:22 »
dovolim si postnuty skript forknout ;-)

Kód: [Vybrat]
#!/bin/bash

# Nastavte cestu, kde chcete hledat soubory, pokud jste nevolal skript s parametrem cesty
SEARCH_DIR="${1:-/cesta/k/hledani}"

# Nastavte názvy výstupních souborů
OUTPUT_FILENAMES="vystup_nazvy_souboru.txt"
OUTPUT_SIZES_AND_FILENAMES="vystup_velikosti_a_nazvy_souboru.txt"
OUTPUT_CSV="vystup_velikosti_a_nazvy_a_adresare.csv"

# Odstraňte existující výstupní soubory
rm -f "${OUTPUT_FILENAMES}" "${OUTPUT_SIZES_AND_FILENAMES}" "${OUTPUT_CSV}"

# Najděte soubory s velikostí mezi 10 a 20 MB
while read file; do
    # Získejte název souboru
    filename="${file##*/}"

    # Získejte adresář souboru
    dirname="${file%/*}"

    # Získejte velikost souboru v bytech
    size=$(stat -c "%s" "${file}")

    # Počítejte celkovou velikost souborů
    total_size=$(( ${total_size} + ${size} ))

    # Přidejte název souboru do prvního souboru
    echo "${filename}" >> "${OUTPUT_FILENAMES}"

    # Přidejte velikost a název souboru do druhého souboru
    echo "${size} ${filename}" >> "${OUTPUT_SIZES_AND_FILENAMES}"

    # Přidejte velikost, název souboru, název adresáře do csv
    echo "${size};${filename};${dirname}" >> ${OUTPUT_CSV}
done < <(find "${SEARCH_DIR}" -type f -size +10M -size -20M)

# Celkovou velikost nalezených souborů přidejte na konec druhého souboru
echo "Celkova velikost: ${total_size}" >> "${OUTPUT_SIZES_AND_FILENAMES}"

Zmeny:
- moznost volat "skript /cesta/k/hledani"
- nedavat while za pipe, ale posilat do done (zjednoduseni a usetri se ruzne problemy)
- vystup dava i do csv vcetne nazvu adresaru
- pro (nejen)prehlednost nazvy promenych uzavrene v {}
- celkovou velikost souborů pocitat rovnou v smycce

Bugsa

  • ***
  • 130
    • Zobrazit profil
    • E-mail
Re:find do dvou souborů
« Odpověď #6 kdy: 28. 04. 2023, 06:41:24 »
Že je ten ChatGPT šikovný, že? :)

Re:find do dvou souborů
« Odpověď #7 kdy: 28. 04. 2023, 07:02:19 »
Že je ten ChatGPT šikovný, že? :)

Jj, pořád mi to přijde neuvěřitelný. Na složitější dotazy občas vymyslí blbost, občas dělá chyby, občas vymyslí něco lepšího než já. Na dotazy jako je ten v tomto vláknu je to naprostý life-saver. Bash jsem se v životě nedokázal naučit víc než `for f in *.txt; do ...; done` a díky bohu (tedy ChatGPT) už vím že nikdy nebudu muset :-)

Karmelos

  • *****
  • 1 073
    • Zobrazit profil
    • E-mail
Re:find do dvou souborů
« Odpověď #8 kdy: 28. 04. 2023, 08:27:10 »
Že je ten ChatGPT šikovný, že? :)

Jj, pořád mi to přijde neuvěřitelný. Na složitější dotazy občas vymyslí blbost, občas dělá chyby, občas vymyslí něco lepšího než já. Na dotazy jako je ten v tomto vláknu je to naprostý life-saver. Bash jsem se v životě nedokázal naučit víc než `for f in *.txt; do ...; done` a díky bohu (tedy ChatGPT) už vím že nikdy nebudu muset :-)

Já myslim, že tady na rootu by měli každé nové téma poslat tlačítkem  [poslat] do chatgpt a výsledek by se s dotazem uložil jako první příspěvek do diskuze.  Bylo by to minimálně zajímavé.
Gréta je nejlepší.

Wolda

  • **
  • 79
  • http://honza.ucw.cz
    • Zobrazit profil
    • E-mail
Re:find do dvou souborů
« Odpověď #9 kdy: 28. 04. 2023, 09:23:27 »
dovolim si postnuty skript forknout ;-)

Kód: [Vybrat]
#!/bin/bash

# Nastavte cestu, kde chcete hledat soubory, pokud jste nevolal skript s parametrem cesty
SEARCH_DIR="${1:-/cesta/k/hledani}"

# Nastavte názvy výstupních souborů
OUTPUT_FILENAMES="vystup_nazvy_souboru.txt"
OUTPUT_SIZES_AND_FILENAMES="vystup_velikosti_a_nazvy_souboru.txt"
OUTPUT_CSV="vystup_velikosti_a_nazvy_a_adresare.csv"

# Odstraňte existující výstupní soubory
rm -f "${OUTPUT_FILENAMES}" "${OUTPUT_SIZES_AND_FILENAMES}" "${OUTPUT_CSV}"

# Najděte soubory s velikostí mezi 10 a 20 MB
while read file; do
    # Získejte název souboru
    filename="${file##*/}"

    # Získejte adresář souboru
    dirname="${file%/*}"

    # Získejte velikost souboru v bytech
    size=$(stat -c "%s" "${file}")

    # Počítejte celkovou velikost souborů
    total_size=$(( ${total_size} + ${size} ))

    # Přidejte název souboru do prvního souboru
    echo "${filename}" >> "${OUTPUT_FILENAMES}"

    # Přidejte velikost a název souboru do druhého souboru
    echo "${size} ${filename}" >> "${OUTPUT_SIZES_AND_FILENAMES}"

    # Přidejte velikost, název souboru, název adresáře do csv
    echo "${size};${filename};${dirname}" >> ${OUTPUT_CSV}
done < <(find "${SEARCH_DIR}" -type f -size +10M -size -20M)

# Celkovou velikost nalezených souborů přidejte na konec druhého souboru
echo "Celkova velikost: ${total_size}" >> "${OUTPUT_SIZES_AND_FILENAMES}"

Zmeny:
- moznost volat "skript /cesta/k/hledani"
- nedavat while za pipe, ale posilat do done (zjednoduseni a usetri se ruzne problemy)
- vystup dava i do csv vcetne nazvu adresaru
- pro (nejen)prehlednost nazvy promenych uzavrene v {}
- celkovou velikost souborů pocitat rovnou v smycce

Ta "< <(program)" syntaxe je bash-only feature, ze? To neni vytka, jen ujistujici dotaz.

OT: K3dar - ten, kdo ve staroveku obhospodaroval linux na Palm T3, nebo jen shoda "jmen"? ;-)

Re:find do dvou souborů
« Odpověď #10 kdy: 28. 04. 2023, 09:27:00 »
Zdravím, no nechci být za škarohlída, ale ten skript teda nic moc efektivita. A to jsem ho ani nezkusil sputit, jestli funguje.
Příkaz find umí fprintf a tedy sám o sobě vyrobit dva soubory. Ten součet se bude muset tedy udělat následně, ale budou to celé dva příkazy. To snad dá dohromady každý. Jako děsím se, že někdo fakt začne používat ty blbosti co z ChatGPT padají...

Re:find do dvou souborů
« Odpověď #11 kdy: 28. 04. 2023, 09:38:24 »
Ahoj, zkusil jsem trochu modifikovat ten posledni kod, protoze jsem to chtel prevest aby ti bylo prehlednejsi, ale nepovedlo se mi to aby to fungovalo. Muzete jeste pomoc? GPT jsem zatim nezkousel, tak daleko jsem se nedostal, jeste jsem neprisel na to jak updatovat Firefox, natoz abych instaloval nejakeho bota. Ale jestli by to umel opravit ... chci to prevest na KB, MB nebo GB tak aby to bylo prehledne. To s tim printf jeste neumim, takze nemam predstavu... Zatim vse moc tezke.


Kód: [Vybrat]
#!/bin/bash

# Nastavte cestu, kde chcete hledat soubory, pokud jste nevolal skript s parametrem cesty
SEARCH_DIR="${1:-/media/user/alfa_c/WINDOWS/system32}"

# Nastavte názvy výstupních souborů
OUTPUT_FILENAMES="output_fn.txt"
OUTPUT_SIZES_AND_FILENAMES="output_sf.txt"
OUTPUT_CSV="output_s_fd.csv"

# Odstraňte existující výstupní soubory
rm -f "${OUTPUT_FILENAMES}" "${OUTPUT_SIZES_AND_FILENAMES}" "${OUTPUT_CSV}"

# Najděte soubory s velikostí mezi 10 a 20 MB
while read file; do
    # Získejte název souboru
    filename="${file##*/}"
    filepath="${file}"

    # Získejte adresář souboru
    dirname="${file%/*}"

    # Získejte velikost souboru v bytech
    size=$(stat -c "%s" "${file}")
    if [ "$size" -ge 1024 ]; then
      size_U=`echo "($size)/1024"|bc`
      size_U=" $size_U KiB"
      if [ "$size" -ge 1048576 ]; then
        size_U=`echo "($size)/1048576"|bc`
        size_U=" $size_U MiB"
        if [ "$size" -ge 1073741824 ]; then
          size_U=`echo "($size)/1073741824U"|bc`
          size_U=" $size_U GiB"
        fi
      fi
    fi

    size=$(size_U)

    # Počítejte celkovou velikost souborů
    total_size=$(( ${total_size} + ${size} ))

    # Přidejte název souboru do prvního souboru
    echo "${filepath}" >> "${OUTPUT_FILENAMES}"

    # Přidejte velikost a název souboru do druhého souboru
    echo "${size} ${filepath}" >> "${OUTPUT_SIZES_AND_FILENAMES}"

    # Přidejte velikost, název souboru, název adresáře do csv
    echo "${size};${filepath};${dirname}" >> ${OUTPUT_CSV}
done < <(find "${SEARCH_DIR}" -type f -size +10M -size -20M)

# Celkovou velikost nalezených souborů přidejte na konec druhého souboru
total_size_K=`echo "($total_size)/1024"|bc`
total_size_M=`echo "($total_size)/1024/1024"|bc`
total_size_G=`echo "($total_size)/1024/1024/1024"|bc`
total_size_K=" $total_size_K KiB"
total_size_M=" $total_size_M MiB"
total_size_G=" $total_size_G GiB"

echo "Celkova velikost: $total_size_G $total_size_M $total_size_K ${total_size}" >> "${OUTPUT_SIZES_AND_FILENAMES}"

Re:find do dvou souborů
« Odpověď #12 kdy: 28. 04. 2023, 09:43:38 »
Example:

Kód: [Vybrat]
zito@bobekpc:~$ find /usr -type f -size +10M -size -20M -fprintf /tmp/seznam-souboru.txt "%p\n" -fprintf /tmp/seznam-velikosti.txt "%s %p\n"
find: ‘/usr/share/polkit-1/rules.d’: Permission denied
zito@bobekpc:~$ perl -ne 'm/^(\d+)/; $sum+=$1; END { print "$sum\n"; }' /tmp/seznam-velikosti.txt >>/tmp/seznam-velikosti.txt
zito@bobekpc:~$ tail /tmp/seznam-velikosti.txt
12488704 /usr/lib/jvm/java-17-openjdk-amd64/lib/server/classes_nocoops.jsa
13499696 /usr/lib/gcc/avr/5.4.0/cc1plus
12225808 /usr/lib/gcc/avr/5.4.0/cc1
11393520 /usr/lib/gcc/avr/5.4.0/lto1
11781496 /usr/lib/python3.11/config-3.11-x86_64-linux-gnu/libpython3.11-pic.a
13289528 /usr/lib/python3.11/config-3.11-x86_64-linux-gnu/libpython3.11.a
10544880 /usr/lib/chromium/icudtl.dat
17194360 /usr/lib/freecad-python3/lib/libFreeCADGui.so
12328522 /usr/lib/udev/hwdb.bin
666858481

Například takhle výše...

Re:find do dvou souborů
« Odpověď #13 kdy: 28. 04. 2023, 10:48:25 »
Václav Ovsik, muzete prosim vysvetlit co dela ten radek s perl? Co je vystupem
Kód: [Vybrat]
perl -ne 'm/^(\d+)/; ? to hleda soubory nebo to ma nejak nacist velikosti z toho predchoziho prikazu... toto absolutne nechapu i kdyz regex rozumim... A proc je tam END? END jako konec smycky v perlu? To asi dava smysl. Nechapu ale jak se dostaly data z find do perl

k3dAR

  • *****
  • 3 071
  • porad nemam telo, ale uz mam hlavu... nobody
    • Zobrazit profil
    • E-mail
Re:find do dvou souborů
« Odpověď #14 kdy: 28. 04. 2023, 11:58:42 »
Ta "< <(program)" syntaxe je bash-only feature, ze? To neni vytka, jen ujistujici dotaz.

OT: K3dar - ten, kdo ve staroveku obhospodaroval linux na Palm T3, nebo jen shoda "jmen"? ;-)
je to rozsireni bashe jestli to umi i nejaky dalsi lepsi shell netusim, pouzivam vsude bash :-)

ad OT: jj, sem to ja :) a to uz bude pres 15let... ve webarchivu to koukam jeste zustalo :)