Génération NTEntraideLinuxAutres OSLinux[bash] lister/copier le contenu situé à la racine d'un dossier sans rien oublier ( comme les dot-files et les « space-files »)
[bash] lister/copier le contenu situé à la racine d'un dossier sans rien oublier ( comme les dot-files et les « space-files »)
38 réponses
Francois Lafont
Bonjour à tous,
J'ai deux soucis. Dans les deux cas, je précise une fois pour toutes que
je souhaite obtenir des solutions qui gèrent correctement les noms de
fichiers avec des espaces (au début et/ou au milieu et/ou à la fin)
ainsi que les fichiers avec un nom de la forme .xxx (ie un dot-file).
1) Je souhaite lister le contenu situé à la racine d'un dossier
/dossier, c'est-à-dire tous les noms des fichiers-dossiers se trouvant à
la racine de /dossier. Alors, je pense naturellement à :
#-------------------------------------
for i in $(ls -A "/dossier"); do
echo "--$i--"
done
#-------------------------------------
Je « chope » bien les dot-files, mais ça coince avec des
fichiers-dossiers dont le nom contient des espaces. C'est un problème
simple mais pourtant je n'ai pas trouvé mieux que ça pour le résoudre :
#-------------------------------------
find "/dossier" -maxdepth 1 -mindepth 1 | while read; do
nom=$(basename "$REPLY")
echo "--$nom--"
done
#-------------------------------------
Y a-t-il plus simple que ça ? (J'espère que oui quand même).
2) Je souhaite copier tout le contenu du dossier /source vers le dossier
/cible.
« cp -r /source /cible » ne marche pas car il copie le dossier "source"
dans le dossier "cible" alors que je veux copier le contenu de "source".
« cp -r /source/* /cible » ne copie pas les dot-files. Si je fais alors
« cp -r /source/.* /cible », pour des raisons que je ne comprends pas
très bien d'ailleurs (si vous avez une explication au passage ça
m'intéresse), il y a tentative de copie de ce qui se trouve « au dessus
» de /source. Là aussi, pour un problème assez simple en somme, je n'ai
pas trouvé mieux que ça :
#-------------------------------------
find "/source" -maxdepth 1 -mindepth 1 | while read; do
cp -r "$REPLY" "/cible"
done
#-------------------------------------
Est-ce que tu as un exemple de nom qui ne marcherait pas dans ce cas là ?
Un nom de fichier avec un n dedans. Il se fera couper en deux.
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#-------------------------------------------- $ ls rep -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa -rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done --rep/aaaa-- --rep/aaaneee-- #--------------------------------------------
Ou alors je n'ai peut-être pas compris ce que tu voulais dire...
Si je comprends bien, si on veut être « béton » au niveau des noms de fichiers, "find ... -print0 | xargs ..." est alors le seul moyen ?
En fait, il y en a un autre, à savoir
find ... -exec commande '{}' +
qui fait faire à find le boulot d'xargs. Et celui-ci est standard (la raison qu'ils invoquent pour avoir inventer le find + plutot que de standardiser le print0 est à se frapper la tete contre les murs). J'ai pris l'habitude d'utiliser print0 et xargs à une époque où GNU find ne supportait pas encore le +, et résultat, je ne pense jamais au find +.
Ok, merci pour l'info.
-- François Lafont
Le 01/03/2012 14:27, Luc Habert a écrit :
Francois Lafont :
Est-ce que tu as un exemple de nom qui ne marcherait pas dans ce cas là ?
Un nom de fichier avec un n dedans. Il se fera couper en deux.
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#--------------------------------------------
$ ls rep -l
total 0
-rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa
-rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done
--rep/aaaa--
--rep/aaaneee--
#--------------------------------------------
Ou alors je n'ai peut-être pas compris ce que tu voulais dire...
Si je comprends bien, si on veut être « béton » au niveau des noms de
fichiers, "find ... -print0 | xargs ..." est alors le seul moyen ?
En fait, il y en a un autre, à savoir
find ... -exec commande '{}' +
qui fait faire à find le boulot d'xargs. Et celui-ci est standard (la raison
qu'ils invoquent pour avoir inventer le find + plutot que de standardiser le
print0 est à se frapper la tete contre les murs). J'ai pris l'habitude
d'utiliser print0 et xargs à une époque où GNU find ne supportait pas encore
le +, et résultat, je ne pense jamais au find +.
Est-ce que tu as un exemple de nom qui ne marcherait pas dans ce cas là ?
Un nom de fichier avec un n dedans. Il se fera couper en deux.
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#-------------------------------------------- $ ls rep -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa -rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done --rep/aaaa-- --rep/aaaneee-- #--------------------------------------------
Ou alors je n'ai peut-être pas compris ce que tu voulais dire...
Si je comprends bien, si on veut être « béton » au niveau des noms de fichiers, "find ... -print0 | xargs ..." est alors le seul moyen ?
En fait, il y en a un autre, à savoir
find ... -exec commande '{}' +
qui fait faire à find le boulot d'xargs. Et celui-ci est standard (la raison qu'ils invoquent pour avoir inventer le find + plutot que de standardiser le print0 est à se frapper la tete contre les murs). J'ai pris l'habitude d'utiliser print0 et xargs à une époque où GNU find ne supportait pas encore le +, et résultat, je ne pense jamais au find +.
Ok, merci pour l'info.
-- François Lafont
Luc.Habert.00__arjf
Francois Lafont :
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#-------------------------------------------- $ ls rep -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa -rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done --rep/aaaa-- --rep/aaaneee--
Ah, j'ai compris notre incompréhension. Quand j'écris n je parle d'un retour à la ligne, tandis que tu comprenais littérallement n, d'où ton recours à read -r.
Francois Lafont :
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#--------------------------------------------
$ ls rep -l
total 0
-rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa
-rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done
--rep/aaaa--
--rep/aaaneee--
Ah, j'ai compris notre incompréhension. Quand j'écris n je parle d'un
retour à la ligne, tandis que tu comprenais littérallement n, d'où ton
recours à read -r.
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#-------------------------------------------- $ ls rep -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa -rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done --rep/aaaa-- --rep/aaaneee--
Ah, j'ai compris notre incompréhension. Quand j'écris n je parle d'un retour à la ligne, tandis que tu comprenais littérallement n, d'où ton recours à read -r.
Francois Lafont
Le 01/03/2012 15:03, Luc Habert a écrit :
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#-------------------------------------------- $ ls rep -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa -rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done --rep/aaaa-- --rep/aaaneee--
Ah, j'ai compris notre incompréhension. Quand j'écris n je parle d'un retour à la ligne, tandis que tu comprenais littérallement n, d'où ton recours à read -r.
Oui, tout à fait. Au temps pour moi. Effectivement, la commande ci-dessus ne fonctionne pas avec un nom de fichier qui possède un retour à la ligne.
Je pensais pas que ce n'était pas possible d'avoir un retour à la ligne dans le nom d'un fichier. Via l'interface graphique, je n'arrive pas à créer un tel fichier. Mais en ligne de commandes, ça passe sans problème :
#------------------------------- $ touch 'aaa
bbb'
$ ls -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 16:41 aaa?bbb #-------------------------------
Merci bien pour toutes ces explications. :-) À+
-- François Lafont
Le 01/03/2012 15:03, Luc Habert a écrit :
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#--------------------------------------------
$ ls rep -l
total 0
-rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa
-rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done
--rep/aaaa--
--rep/aaaneee--
Ah, j'ai compris notre incompréhension. Quand j'écris n je parle d'un
retour à la ligne, tandis que tu comprenais littérallement n, d'où ton
recours à read -r.
Oui, tout à fait. Au temps pour moi. Effectivement, la commande
ci-dessus ne fonctionne pas avec un nom de fichier qui possède un retour
à la ligne.
Je pensais pas que ce n'était pas possible d'avoir un retour à la ligne
dans le nom d'un fichier. Via l'interface graphique, je n'arrive pas à
créer un tel fichier. Mais en ligne de commandes, ça passe sans problème :
#-------------------------------
$ touch 'aaa
bbb'
$ ls -l
total 0
-rw-r--r-- 1 francois francois 0 1 mars 16:41 aaa?bbb
#-------------------------------
Sur ma Debian Squeeze, ça n'a pas l'air de poser problème :
#-------------------------------------------- $ ls rep -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 14:19 aaaa -rw-r--r-- 1 francois francois 0 1 mars 14:26 aaaneee
$ find rep/ -type f | while read -r; do echo "--$REPLY--"; done --rep/aaaa-- --rep/aaaneee--
Ah, j'ai compris notre incompréhension. Quand j'écris n je parle d'un retour à la ligne, tandis que tu comprenais littérallement n, d'où ton recours à read -r.
Oui, tout à fait. Au temps pour moi. Effectivement, la commande ci-dessus ne fonctionne pas avec un nom de fichier qui possède un retour à la ligne.
Je pensais pas que ce n'était pas possible d'avoir un retour à la ligne dans le nom d'un fichier. Via l'interface graphique, je n'arrive pas à créer un tel fichier. Mais en ligne de commandes, ça passe sans problème :
#------------------------------- $ touch 'aaa
bbb'
$ ls -l total 0 -rw-r--r-- 1 francois francois 0 1 mars 16:41 aaa?bbb #-------------------------------
Merci bien pour toutes ces explications. :-) À+
-- François Lafont
xavier
Francois Lafont wrote:
2) Je souhaite copier tout le contenu du dossier /source vers le dossier /cible.
Pour lister, j'ai pas d'idé géniale. Pour copier, pax(1) fait très bien l'affaire:
1) Je souhaite lister le contenu situé à la racine d'un dossier /dossier
En shell:
for f in "$dir"/* "$dir"/.[!.]* "$dir"/..?*; do test -e "$f" || continue; # si un pattern ne matche rien, il est expansé # en lui-même et non en rien
Pour ça on peut utiliser l'option nullglob.
# do something with $f done
-- LL
Francois Lafont
Je remonte ce fil pour réagir à ceci :
Le 29/02/2012 18:18, YBM a écrit :
Ce que j'en ai gardé en tête, pour des situations similaire c'est
cp -a source/. cible/ # si peu de données (cd source ; tar cf - .) | (cd cible ; tar xf -) # si beaucoup de données
la seconde solution se trouvant terriblement performante.
Par ailleurs, y a-t-il des soucis « connus » au niveau de la commande cp quant à des copies qui passent par le réseau ?
En effet, j'ai eu des copies ratées avec la commande cp d'un répertoire /mnt/d qui correspond à un montage cifs vers un répertoire local /home/d.
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
Et le fichier en question n'était pas identique à la source ! Pourtant; la copie portait sur une quantité de données de 500 Ko ce qui n'est pas énorme. (Je n'arrive plus à reproduire l'erreur.)
1) Elle signifie quoi cette erreur ? Qu'au moment de la copie du fichier, celui-ci est écrit par un autre programme ou un truc dans le genre ?
2) Sur le Web, on trouve beaucoup de fils dans les forums où ce message d'erreur est cité. C'est un petit bug de cp ou ou bien le montage cifs de mon répertoire /mnt/d n'est pas correct ?
-- François Lafont
Je remonte ce fil pour réagir à ceci :
Le 29/02/2012 18:18, YBM a écrit :
Ce que j'en ai gardé en tête, pour des situations similaire c'est
cp -a source/. cible/ # si peu de données
(cd source ; tar cf - .) | (cd cible ; tar xf -) # si beaucoup de données
la seconde solution se trouvant terriblement performante.
Par ailleurs, y a-t-il des soucis « connus » au niveau de la commande cp
quant à des copies qui passent par le réseau ?
En effet, j'ai eu des copies ratées avec la commande cp d'un répertoire
/mnt/d qui correspond à un montage cifs vers un répertoire local /home/d.
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec
comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
Et le fichier en question n'était pas identique à la source ! Pourtant;
la copie portait sur une quantité de données de 500 Ko ce qui n'est pas
énorme. (Je n'arrive plus à reproduire l'erreur.)
1) Elle signifie quoi cette erreur ? Qu'au moment de la copie du
fichier, celui-ci est écrit par un autre programme ou un truc dans le
genre ?
2) Sur le Web, on trouve beaucoup de fils dans les forums où ce message
d'erreur est cité. C'est un petit bug de cp ou ou bien le montage cifs
de mon répertoire /mnt/d n'est pas correct ?
Ce que j'en ai gardé en tête, pour des situations similaire c'est
cp -a source/. cible/ # si peu de données (cd source ; tar cf - .) | (cd cible ; tar xf -) # si beaucoup de données
la seconde solution se trouvant terriblement performante.
Par ailleurs, y a-t-il des soucis « connus » au niveau de la commande cp quant à des copies qui passent par le réseau ?
En effet, j'ai eu des copies ratées avec la commande cp d'un répertoire /mnt/d qui correspond à un montage cifs vers un répertoire local /home/d.
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
Et le fichier en question n'était pas identique à la source ! Pourtant; la copie portait sur une quantité de données de 500 Ko ce qui n'est pas énorme. (Je n'arrive plus à reproduire l'erreur.)
1) Elle signifie quoi cette erreur ? Qu'au moment de la copie du fichier, celui-ci est écrit par un autre programme ou un truc dans le genre ?
2) Sur le Web, on trouve beaucoup de fils dans les forums où ce message d'erreur est cité. C'est un petit bug de cp ou ou bien le montage cifs de mon répertoire /mnt/d n'est pas correct ?
-- François Lafont
Luc.Habert.00__arjf
Francois Lafont :
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
D'après le code source, ça signifie que cp a obtenu le nom du fichier, a fait un stat dessus pour obtenir des infos dessus, l'a ouvert, a fait un fstat sur le file descriptor obtenu, et le fstat a pondu des infos différentes du stat précédent.
C'est normal si un autre programme (éventuellement à distance) a effacé le fichier et mis un autre fichier sous le même nom entre l'appel à stat et l'ouverture du fichier. Sinon, c'est un bug (coté serveur ou client).
Et le fichier en question n'était pas identique à la source !
Beuh cp a copié le fichier? Il disait qu'il le sautait.
Francois Lafont :
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec
comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
D'après le code source, ça signifie que cp a obtenu le nom du fichier, a
fait un stat dessus pour obtenir des infos dessus, l'a ouvert, a fait un
fstat sur le file descriptor obtenu, et le fstat a pondu des infos
différentes du stat précédent.
C'est normal si un autre programme (éventuellement à distance) a effacé le
fichier et mis un autre fichier sous le même nom entre l'appel à stat et
l'ouverture du fichier. Sinon, c'est un bug (coté serveur ou client).
Et le fichier en question n'était pas identique à la source !
Beuh cp a copié le fichier? Il disait qu'il le sautait.
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
D'après le code source, ça signifie que cp a obtenu le nom du fichier, a fait un stat dessus pour obtenir des infos dessus, l'a ouvert, a fait un fstat sur le file descriptor obtenu, et le fstat a pondu des infos différentes du stat précédent.
C'est normal si un autre programme (éventuellement à distance) a effacé le fichier et mis un autre fichier sous le même nom entre l'appel à stat et l'ouverture du fichier. Sinon, c'est un bug (coté serveur ou client).
Et le fichier en question n'était pas identique à la source !
Beuh cp a copié le fichier? Il disait qu'il le sautait.
Francois Lafont
Je réponds un peu tardivement à ce message qui vient de tomber récemment sur mon lecteur de news.
Le 05/03/2012 01:20, Luc Habert a écrit :
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
D'après le code source, ça signifie que cp a obtenu le nom du fichier, a fait un stat dessus pour obtenir des infos dessus, l'a ouvert, a fait un fstat sur le file descriptor obtenu, et le fstat a pondu des infos différentes du stat précédent.
Ok, merci.
C'est normal si un autre programme (éventuellement à distance) a effacé le fichier et mis un autre fichier sous le même nom entre l'appel à stat et l'ouverture du fichier. Sinon, c'est un bug (coté serveur ou client).
Et le fichier en question n'était pas identique à la source !
Beuh cp a copié le fichier? Il disait qu'il le sautait.
Comme je disais, je n'ai malheureusement jamais pu reproduire l'erreur et en fait (il était un peu tard à ce moment là) il est possible que le message d'erreur indiqué citait un certain fichier et le fichier source différent du fichier cible était peut-être un autre fichier, honnêtement je ne sais plus trop.
En revanche, ce dont je suis absolument sur, c'est que j'avais une simple commande « cp -r /mnt/d1 /home/toto/ » (avec /mnt/d1 un montage cifs et /home/toto un répertoire « local ») et dans d1 j'avais un fichier texte, appelons-le f, tout bête et pas bien gros (10 lignes max) alors que sa copie /home/toto/f était foireuse. Un « cat /home/toto/f » me retournait seulement la première ligne de f et c'est tout. Quand je faisais « cat /home/toto/f » je voyais bien les caractères de la première ligne s'afficher et ensuite plein de partout. J'ai eu ce problème de copie foireuse au moins 4 ou 5 fois de suite et après je n'ai jamais réussi à reproduire l'erreur.
-- François Lafont
Je réponds un peu tardivement à ce message qui vient de tomber récemment
sur mon lecteur de news.
Le 05/03/2012 01:20, Luc Habert a écrit :
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec
comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
D'après le code source, ça signifie que cp a obtenu le nom du fichier, a
fait un stat dessus pour obtenir des infos dessus, l'a ouvert, a fait un
fstat sur le file descriptor obtenu, et le fstat a pondu des infos
différentes du stat précédent.
Ok, merci.
C'est normal si un autre programme (éventuellement à distance) a effacé le
fichier et mis un autre fichier sous le même nom entre l'appel à stat et
l'ouverture du fichier. Sinon, c'est un bug (coté serveur ou client).
Et le fichier en question n'était pas identique à la source !
Beuh cp a copié le fichier? Il disait qu'il le sautait.
Comme je disais, je n'ai malheureusement jamais pu reproduire l'erreur
et en fait (il était un peu tard à ce moment là) il est possible que le
message d'erreur indiqué citait un certain fichier et le fichier source
différent du fichier cible était peut-être un autre fichier, honnêtement
je ne sais plus trop.
En revanche, ce dont je suis absolument sur, c'est que j'avais une
simple commande « cp -r /mnt/d1 /home/toto/ » (avec /mnt/d1 un montage
cifs et /home/toto un répertoire « local ») et dans d1 j'avais un
fichier texte, appelons-le f, tout bête et pas bien gros (10 lignes max)
alors que sa copie /home/toto/f était foireuse. Un « cat /home/toto/f »
me retournait seulement la première ligne de f et c'est tout. Quand je
faisais « cat /home/toto/f » je voyais bien les caractères de la
première ligne s'afficher et ensuite plein de partout. J'ai eu ce
problème de copie foireuse au moins 4 ou 5 fois de suite et après je
n'ai jamais réussi à reproduire l'erreur.
Je réponds un peu tardivement à ce message qui vient de tomber récemment sur mon lecteur de news.
Le 05/03/2012 01:20, Luc Habert a écrit :
La copie (récursive) se faisait jusqu'au bout (enfin je crois) avec comme message à un moment :
« cp: skipping file xxx as it was replaced while being copied » .
D'après le code source, ça signifie que cp a obtenu le nom du fichier, a fait un stat dessus pour obtenir des infos dessus, l'a ouvert, a fait un fstat sur le file descriptor obtenu, et le fstat a pondu des infos différentes du stat précédent.
Ok, merci.
C'est normal si un autre programme (éventuellement à distance) a effacé le fichier et mis un autre fichier sous le même nom entre l'appel à stat et l'ouverture du fichier. Sinon, c'est un bug (coté serveur ou client).
Et le fichier en question n'était pas identique à la source !
Beuh cp a copié le fichier? Il disait qu'il le sautait.
Comme je disais, je n'ai malheureusement jamais pu reproduire l'erreur et en fait (il était un peu tard à ce moment là) il est possible que le message d'erreur indiqué citait un certain fichier et le fichier source différent du fichier cible était peut-être un autre fichier, honnêtement je ne sais plus trop.
En revanche, ce dont je suis absolument sur, c'est que j'avais une simple commande « cp -r /mnt/d1 /home/toto/ » (avec /mnt/d1 un montage cifs et /home/toto un répertoire « local ») et dans d1 j'avais un fichier texte, appelons-le f, tout bête et pas bien gros (10 lignes max) alors que sa copie /home/toto/f était foireuse. Un « cat /home/toto/f » me retournait seulement la première ligne de f et c'est tout. Quand je faisais « cat /home/toto/f » je voyais bien les caractères de la première ligne s'afficher et ensuite plein de partout. J'ai eu ce problème de copie foireuse au moins 4 ou 5 fois de suite et après je n'ai jamais réussi à reproduire l'erreur.