Vous voulez créer des fichiers txt pour chaque png dans le dossier


12

J'ai ce script

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in $folder/*
do
touch $filePng.txt
done

Cela fonctionne, juste que, pour un fichier nommé 001.png, il crée à la 001.png.txtplace de 001.txt.

Comment puis-je modifier cela?


4
C'est une bonne habitude d'entrer pour citer vos variables. Le script shell est un langage étrange qui a évolué au fil du temps plutôt que d'être parfaitement conçu dès le départ, donc malheureusement des choses ennuyeuses comme celle-ci deviennent nécessaires. Sans citer vos variables, les espaces ou les astérisques dans le contenu des variables provoqueront des ruptures étranges. Pour rendre vos scripts plus robustes, entourez toujours les utilisations de vos variables de guillemets doubles. Ici, vous diriez for filePng in "$folder"/*et touch "$filePng".txt - notez que vous ne les citez que lorsqu'ils sont précédés d'un $.
Muzer

3
Cela ressemble à un problème XY… Pourquoi essayez-vous de faire cela?
JeromeJ

Réponses:


16

Vous pouvez utiliser la basenamecommande ici:

touch "$folder/$(basename "$filePng" .png).txt"

Notez les supplémentaires $folder/. Ceci est nécessaire car la commande basename supprime le chemin d'accès.


Puis-je suggérer que vous ayez cité l'expansion de vos paramètres et la substitution de commandes?
Tom Fenech

@ TomFenech oui, probablement une bonne idée de citer toute la chaîne. J'ai édité ma réponse.
Wayne_Yux

Je ne sais pas pourquoi vous avez supprimé les guillemets intérieurs $filePng- ils étaient également utiles.
Tom Fenech

1
Non, car $( )établit un nouveau contexte de citation.
Tom Fenech

2
Oh, vous avez raison - appris quelque chose de nouveau aujourd'hui ;-)
Wayne_Yux

31

Vous pouvez supprimer l'extension existante à l'aide des fonctionnalités d' extension des paramètres du shell

${parameter%pattern}Le «modèle» est comparé à la fin du «paramètre». Le résultat est la valeur étendue de «paramètre» avec la correspondance la plus courte supprimée.

Donc dans votre cas, remplacez $filePng.txtpar"${filePng%.png}.txt"


10

Avec des variations sur ce que Steeldriver a déjà mentionné - l'expansion des paramètres - nous pouvons utiliser le remplacement de chaîne pour faire le travail. De plus, vous devez citer des variables. Vous trouverez ci-dessous votre script modifié.

#!/bin/bash

folder='/home/data/mnist/training'

for filePng in "$folder"/*
do
    touch "${filePng/.png/.txt}"
done

9

Si vous avez beaucoup de fichiers à créer, il vaudrait la peine de «toucher» plus d'un fichier à la fois, de sorte que vous n'avez pas besoin de créer un nouveau processus pour chacun d'entre eux (ce qui prend un certain temps s'il est exécuté plusieurs fois). mille fois).

Option 1: substitution de modèle + xargs

Cette option fournira plusieurs chemins d'accès à la touchcommande à la fois, généralement quelques milliers ou tout ce que le système peut contenir sur une seule ligne de commande.

find "$folder" -mindepth 1 -maxdepth 1 -name '*.png' -print0 |
sed -ze 's/\.png$/.txt/' |
xargs -r0 -- touch --

Option 2: extension des paramètres + redirection de la sortie des commandes

Cette option ne s'exécute pas touchdu tout, mais utilise à la place les fonctionnalités du shell Bash / Bourne / POSIX qui ne nécessitent aucun sous-processus.

for f in "$folder"/*.png; do
    : >> "${f%.png}.txt"
done

4

Si vous êtes sûr de ne pas avoir de fichiers avec .pngquelque part au milieu du nom, vous pouvez simplement utiliser un tableau avec une extension de paramètre:

pngs=( /path/to/pngs/*.png )
touch "${pngs[@]/.png/.txt}"

Cela stocke tous les chemins d'accès aux fichiers se terminant par .pngun tableau, puis utilise l'expansion des paramètres pour créer la liste des .txtfichiers, en les remplaçant .pngpar .txtchacun d'eux.

Gardez à l'esprit que cela se cassera si vous avez tellement de fichiers qu'ils ne peuvent pas tous être passés en arguments à la même invocation de touch.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.