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
Comment puis-je obtenir tous les enregistrements de tous les fichiers de tous les dossiers et les enregistrer sous single_file.txt
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 ...
:
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 ...
:
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
:
@ 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
où 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
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.
- 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
for d in ~/Desktop/logs/* ; do
boucle sur le contenu de ~/Desktop/logs
et fait quelque chose avec euxif [[ -d "$d" ]]; then
ne fait quelque chose que si $d
est un répertoirefind "$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 utiliserxargs -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éesLa 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