web-dev-qa-db-fra.com

Comment trouver les journaux qui contiennent certaines chaînes dans de nombreux fichiers gz / réguliers et les enregistrer en tant qu'un ou plusieurs fichiers txt?

Nouvelle question le 22.9.2016, en bas!

Mon chemin ressemble à ceci:

~/Desktop/logs
├── first_folder
|   ├── 11.11 (folder)
│   |   ├── access_log
│   |   ├── access_log.1.gz
│   |   :
│   |   └── access_log.40.gz
|   └── 11.12 (folder)
│       ├── access_log
│       ├── access_log.1.gz
│       :
│       └── access_log.16.gz
├── second_folder (folder)
|   ├── 31.11 (folder)
│   |   ├── access_log
│   |   ├── access_log.1.gz
│   |   :
│   |   └── access_log.20.gz
|   └── 31.15 (folder)
│       ├── access_log
│       ├── access_log.1.gz
│       :
:       └── access_log.38.gz
└── last_folder
    ├── 91.11 (folder)
    |   ├── access_log
    |   ├── access_log.1.gz
    |   :
    |   └── access_log.25.gz
    └── 91.15 (folder)
        ├── access_log
        ├── access_log.1.gz
        :
        └── access_log.30.gz

De tous les journaux, je dois extraire les données qui contiennent la chaîne: /Jan/2016

Question 1

Comment puis-je obtenir tous les enregistrements de tous les fichiers de tous les dossiers et les enregistrer sous single_file.txt

Edit # 1

Réponse possible:

$ find . -name \*.* | xargs -0 zgrep -E '/Jan/2016' > single_file.txt

Le fichier est vraiment très gros, beaucoup de Go.

Sortie:

single_file.txt
./first_folder/11.11/access_log.9.gz: ... text ...
./first_folder/11.12/access_log.9.gz: ... text ...
./second_folder/31.11/access_log.9.gz: ... text ...
./second_folder/31.11/access_log.9.gz: ... text ...
:

Question 2

Comment obtenir tous les enregistrements de tous les fichiers de tous les dossiers et les enregistrer individuellement en fonction des enregistrements saisis dans first_folder, second_folder, etc., comme first.txt, second.txt.

La sortie ressemblerait à quelque chose comme:

first.txt
./first_folder/11.11/access_log.9.gz: ... text ...
./first_folder/11.12/access_log.9.gz: ... text ...
:
second.txt
./second_folder/31.11/access_log.9.gz: ... text ...
./second_folder/31.15/access_log.9.gz: ... text ...
:

Question 3

Comment obtenir la liste de tous les fichiers contenant la chaîne /Jan/2016?

Si j'utilise cette commande, va-t-il récupérer tous les fichiers:

$ find ~/Desktop/logs/ -type f | xargs zgrep -l "/Jan/2016"  

Sortie:

Terminal
/home/name/Desktop/logs/first_folder/11.11/access_log.9.gz
/home/name/Desktop/logs/first_folder/11.12/access_log.8.gz
/home/name/Desktop/logs/second_folder/31.11/access_log.6.gz
:

Edit # 2

@ waltinator-s code et @ Zanna-s correction:

pushd ~/Desktop/logs
for dir in * ; do
    if [[ -d "$dir" ]] ; then
        outname="$dir.txt"
        find "$dir" -type f -print0 | xargs -0 zgrep -l '/Jan/2016' >"$outname"
    fi
done
popd

va me donner une structure:

~/Desktop/logs
├── first_folder
|   └── first.txt
├── second_folder
|   └── second.txt
:
└── last_folder
    └── last.txt

first.txt-last.txt contiendra des chemins vers des fichiers spécifiques contenant la chaîne/Jan/2016.

first.txt
first_folder/11.11/access_log.9.gz
first_folder/11.11/access_log.8.gz
first_folder/11.12/access_log.9.gz
first_folder/11.12/access_log.8.gz

Question n ° 4 (22.9.2016)

J'avais besoin de modifier /Jan/2016 à une certaine période de temps ... par exemple 1/Nov/2014-31/Apr/2015 donc dans un code que @Zana a fourni à la place du /Jan/2016 j'ai utilisé /(Nov|Dec)/2014|/(Jan|Feb|Mar|Apr)/2015. Un avertissement est lancé:

xargs: Warning: a NUL character occurred in the input.  It cannot be passed through in the argument list.  Did you mean to use the --null option?

Tous les résultats ne sont pas renvoyés dans les fichiers créés, même si tous les fichiers sont créés.

3
vayacondios2015
  1. Les données contenant des chaînes de caractères dans des fichiers texte distincts en fonction du dossier (exemple: premier dossier - premier.txt, etc.)

Vous pouvez utiliser une boucle très simple pour créer un fichier texte avec les enregistrements de ce répertoire à l'intérieur du répertoire:

for d in ~/Desktop/logs/* ; do zgrep -E '/Jan/2016' "$d"/* >"$d"/out.txt ; done

Desktop/logs
├── first_folder
│   ├── access_log
│   ├── access_log.gz
│   └── out.txt
└── second_folder
    ├── access_log
    ├── access_log.gz
    └── out.txt

En utilisant ce léger ajustement à script de waltinator :

for d in ~/Desktop/logs/* ; do
    if [[ -d "$d" ]] ; then
        outname="$d".txt
        find "$d" -type f -print0 | xargs -0 zgrep -E '/Jan/2016' >"$outname"
    fi
done

donnera cette structure:

├── first_folder
│   ├── access_log
│   └── access_log.gz
├── first_folder.txt
├── second_folder
│   ├── access_log
│   └── access_log.gz
└── second_folder.txt

Remarques

  • for d in ~/Desktop/logs/* ; do boucle sur le contenu de ~/Desktop/logs et fait quelque chose avec eux
  • if [[ -d "$d" ]]; then ne fait quelque chose que si $d est un répertoire
  • find "$d" -type f -print0 recherche dans les répertoires $d pour les fichiers et les affiche avec le séparateur nul afin que nous puissions utiliser
  • xargs -0 construit une commande avec la sortie de la commande précédente comme arguments, en utilisant le caractère nul comme séparateur (sinon les noms de fichiers avec des espaces interrompent cette approche)
  • zgrep recherche dans les archives compressées
3
Zanna

La manière moderne d'utiliser find, sachant que vous verrez éventuellement un nom de fichier contenant des espaces, est d'utiliser -print0 et xargs -0:

# list all filenames containing '/Jan/2016'
find ~/Desktop/logs -type f -print0 | xargs -0 zgrep -l '/Jan/2016'
# 1. Have all the data from all folders that contain that string under one text file
find ~/Desktop/logs -type f -print0 | xargs -0 zgrep -l '/Jan/2016' >one.text.file
#
# 2. Have data that contains string in a separate text files depending on a folder (example: first folder - first.txt etc)
pushd ~/Desktop/logs
for dir in * ; do
    if [[ -d "$dir" ]] ; then
        outname="$dir.txt"
        find "~/Desktop/logs/$dir" -type f -print0 | xargs -0 zgrep -l '/Jan/2016' >"$outname"
    fi
done
popd
4
waltinator