11
votes

Comment itération via tous les fichiers d'un répertoire commandé par date créé, certains noms de fichiers ont des espaces dans leurs noms.

Tout d'abord, j'avais

for file in `find . -printf "%T@ %Tc %p\n" | sort -n` ; do
  #blah
done


9 commentaires

N'utilisez pas la sortie ls pour quoi que ce soit. LS est un outil de recherche de manière interactive des métadonnées de répertoires. Toute tentative d'analyse ls la sortie avec code est cassée. Les globs globaux sont beaucoup plus simples et correct: pour fichier in * .txt . Lire Analysing LS


@Phildo, "J'ai trouvé des tonnes de variations" - choisissez l'une de ces variations et l'ajoutez à la question comme point de départ. Supprimer quelque chose est souvent plus simple que d'ajouter.


La plupart des systèmes de fichiers ne stockent pas du tout un temps de création d'un fichier. Sur ceux qui font, vous avez besoin d'outils non standard pour la récupérer. Essayez -Newerbb dans gnu trouver par exemple.


@Ranyalbegwein la plupart des systèmes de fichiers? vraiment? est ls -t pas un outil standard? Comment ça marche? Je n'ai pas vraiment besoin de récupérer les données de temps de manière standard, je veux juste des noms de fichiers raisonnablement triés (donc même si les systèmes de fichiers diffèrent, tant que les comparaisons sont cohérentes, je devrais être bonne?)


Oui. LS -T Triera par Modification TIME, où le dernier apparaît en premier. Quoi qu'il en soit, analyser ls est faux.


Pour expliquer le point de @ Rany, de nombreux systèmes de fichiers Unix ne stockent pas le temps de création, que la dernière fois de dernière modification. Voir, par exemple, Cette question et réponses sur UNIX / LINIX SE. Si vous créez les fichiers, vous pouvez mettre le temps de création dans le nom de fichier ou l'enregistrer ailleurs.


La voie 100% sûre et portable (par portable, je ne veux pas dire à travers les coquilles, je veux dire à travers les systèmes ayant installé Bash) consiste à utiliser un algorithme de tri, par exemple, celui qui donne dans Cette réponse .


@Phildo, c'est un outil standard, mais ce n'est pas un outil standard conçu pour une utilisation programmatique . Il existe une proposition d'apporter une prise en charge de la sortie délimitée à la norme POSIX-Standard LS ; Lorsque cela se produit, et non auparavant, cela sera utilisable de manière fiable comme décrit.


Voir c'est-à-dire. Stackoverflow.com/a/40663567/14122 pour une solution véritablement robuste (aucune limite sur le nombre maximal de noms de fichiers avant la commande de tri est cassé; aucune limitation sur laquelle les noms peuvent être présents).


3 Réponses :


8
votes

Utiliser trouver en combinaison avec xargs pour transmettre les noms de fichiers avec une séparation NUL-octet et utilisez un pendant Lire la boucle d'efficacité et d'espace Préservation: xxx

Recherche génère la liste des fichiers, ls les organise, par heure dans ce cas. Pour inverser l'ordre de tri, remplacez -t avec -tr . Si vous vouliez trier par taille, remplacez -t avec -s .

exemple: xxx

En complétude, je soulignerai un point de commentaires à la question suivante: -t est le tri par temps de modification, qui n'est pas un temps de création strictement. Le système de fichiers sur lequel ces fichiers résident dictent si le temps de création ou non est disponible. Étant donné que vos tentatives initiales utilisées -t , j'ai figuré le temps de modification était ce que vous étiez préoccupé, même si ce n'est pas pédantiquement vrai.

Si vous voulez la création, vous aurez Pour le tirer de certaines sources, comme Stat ou le nom du fichier si son encodé là-bas. Cela signifie fondamentalement remplacer le xargs -0 ls -t avec une commande appropriée de la commande sur trier , quelque chose comme: xargs -0 stat -c '% w' | Trier -n


11 commentaires

Ok, attends je pense que c'est sur la bonne voie, laissez-moi clarifier quelques choses et je vous donnerai une réponse acceptée - il semble que l'argument ls devrait être juste -t :: avec -Lt Je suis resté avec tous les métadonnées de fichier dans $ Fichier . De plus, si vous passez dans chaque fichier par lui-même sur ls , est-ce qui les trite réellement? Ou simplement "trier la liste d'un" et donc les quitter comme triés par trouver?


Ouais, le -l était pour le diagnostic. Je l'ai supprimé et remplacé par un exemple - qui peut également répondre à votre deuxième question.


Pourquoi avez-vous réellement besoin trouver ici? seulement pour filtrer les fichiers réguliers? Au fait, votre commande est cassée pour les noms de fichiers contenant des nouvelles lignes (ne peut pas être corrigé), les barres obliques backslashes (peuvent être corrigées avec l'option -r sur lire ) ou des espaces de fuite (Peut être corrigé par Prepending ifs = à la commande lis ); Il est également brisé s'il y a trop de fichiers (la rupture est introduite par l'utilisation de trouver / xargs ). En fait, votre trouver / xargs combo (qui n'est pas standard) peut être remplacé par He plus standard trouver / chemin / vers / dir-dupe f -exec ls -t {} + (et ce sera aussi plus efficace).


@gniourf_gniourf Pouvez-vous fournir un exemple de test à cela? Est-ce que la même chose s'applique à la réponse que j'ai donnée ci-dessous?


Et si vous ne voulez pas filtrer les fichiers réguliers et la recueille (qui ne semble pas être dans les exigences de l'OP), LS -T / PATH / TO / DIR | tandis que ifs = lisez-le -r. faire truc_with "$ dossier"; fait .


@gniourf_gniourf c'est la réponse élégante que je cherchais. Il s'avère que ma réponse était fausse et je l'ai supprimée.


@Brycevrev: Pour les noms de fichiers contenant de nouvelles lignes, essayez juste avec toucher $ 'A \ nnewlines' . Pour les noms de fichiers contenant des espaces de fin, touchez 'fichier avec des espaces de fuite' . Pour les noms de fichiers contenant les backslashes: touchez 'nom_fichith_with_wackslash \ n' . Pour trop de noms de fichiers, créez simplement un tas de fichiers ( un groupe dépend de votre système). Voir, par exemple, Cette page


@gniourf_gniourf J'ai répondu de cette façon parce que c'était le plus proche de l'esprit à ce que l'OP a essayé. Ce n'est ni la façon la plus efficace, la plus portable et la plus correcte de le faire. Cependant, étant proches comme à la tentative initiale de l'OP, sa forme est reconnaissable.


Pas cette fermeture puisque vous introduisez trouver pour modifier le comportement (fichiers réguliers de filtrage et filtrage). Et au moins, corrigez votre Lecture Commande: ifs = fichier lecture -r .


Ce n'est pas un ordre absolu - il est uniquement commandé dans des invocations individuelles de LS -T . S'il y a suffisamment de noms de fichiers pour que cela soit divisé en des invocations distinctes, l'ordre mondial est cassé.


@CHARLESDUFFY vrai que.



-2
votes

Vous pouvez définir temporairement votre variable IFS pour éviter le problème avec des espaces (grâce à http://www.linuxjournal.com/article/10954?page=0,1 ) XXX

Edit: Cela a fonctionné sur Ubuntu, mais pas Rhel6. L'alternative suggérée par évêque semble être plus portable, par exemple: xxx


5 commentaires

Je n'arrive pas à reproduire cela sur ma distribution.


Mais maintenant, cela rompt s'il existe des noms de fichiers avec de nouvelles lignes ou des caractères globaux.


@ T.J. N'utilisez pas la sortie ls pour quoi que ce soit. LS est un outil de recherche de manière interactive des métadonnées de répertoires. Toute tentative d'analyse ls la sortie avec code est cassée. Les globs globaux sont beaucoup plus simples et correct: pour fichier in * .txt . Lire Analysing LS


@Ranyalbegwein: Vous avez raison, mais ici, le problème est de régler le temps de modification de la WRT. Cela ne peut pas être fait avec des globs. Il ne peut pas être fait en toute sécurité sans sérialiser certains horodatages et en utilisant un outil de tri non standard (par exemple, GNU Trier avec l'option -z ) ou à l'aide d'un algorithme de tri ( Par exemple, celui de Cette réponse ).


Juste, cela semble fonctionner uniquement sur Ubuntu, pas Rhel6. (Ne tirez pas sur le messager). Cette alternative (par évêque) fonctionne sur RHEL6: LS -T | en lecture x; Faire



1
votes

Utilisation de gnu Recherche et gnu Trier , on peut procéder comme suit: xxx

Ceci fonctionne comme suit:

  • Recherche imprime sa sortie dans le format . .
  • Trier Tries numériquement - Ainsi, par temps de modification, exprimée en quelques secondes depuis EPOCH.
  • ifs = '' Lire -r -d '' MTIME lit tout à l'espace dans la variable MTime .
  • ifs = '' Lire -r -d '' 'Nom de fichier lit tout le contenu restant jusqu'au nul dans la variable nom de fichier

    Parce que NUL ne peut pas exister dans des noms de fichiers (par rapport aux nouvelles lignes, que peut ), cela ne peut être jeté par des noms avec des contenus surprenants. Voir Bashfaq # 3 pour une discussion détaillée.

    De plus, car il ne dépend pas de passer des noms de passage en tant qu'arguments de ligne de commande à LS -T (qui, comme toutes les autres commandes externes, ne peut accepter qu'un nombre limité d'arguments de ligne de commande sur chaque appel), cette approche n'est pas limité dans le nombre de fichiers qu'il peut trier de manière fiable. (En utilisant trouver ... -exec ls -t {} + ou ... | xargs ls -t entraînera des résultats incorrects silencieusement lorsque le nombre de noms de fichiers en cours de traitement Growe plus grand que le nombre qui peut être transmis à un seul ls invocation).


0 commentaires