Comment puis-je générer une liste de fichiers avec leur chemin absolu sous Linux?

304

J'écris un script shell qui prend les chemins de fichiers en entrée.

Pour cette raison, je dois générer des listes de fichiers récursifs avec des chemins d'accès complets. Par exemple, le fichier bara le chemin:

/home/ken/foo/bar

mais, pour autant que je puisse voir, les deux lset findne donnent que des listes de chemins relatifs:

./foo/bar   (from the folder ken)

Cela semble être une exigence évidente, mais je ne vois rien dans les pages de manuel findou ls.

Comment puis-je générer une liste de fichiers dans le shell, y compris leurs chemins absolus?

Ken
la source
utilisation:find /home/ken/foo/bar -exec ls -ld $PWD/{} \;
Apprenant

Réponses:

305

Si vous donnez findun chemin absolu pour commencer, il imprimera des chemins absolus. Par exemple, pour rechercher tous les fichiers .htaccess dans le répertoire courant:

find "$(pwd)" -name .htaccess

ou si votre shell se développe $PWDdans le répertoire courant:

find "$PWD" -name .htaccess

find ajoute simplement le chemin qui lui a été donné à un chemin relatif vers le fichier à partir de ce chemin.

Greg Hewgill a également suggéré d'utiliser pwd -Psi vous souhaitez résoudre les liens symboliques dans votre répertoire actuel.

Matthew Scharley
la source
9
Notez que si vous souhaitez également résoudre les liens symboliques, utilisez pwd -P.
Greg Hewgill
5
Ceci est utile, mais je pense que la réponse de user431529 ci-dessous est plus valide: ls -d -1 $PWD/**/*mais je suppose que cela find $PWDfonctionne aussi (testé en bash)
Brian
9
@Brian Pourquoi? find $PWDest simple. L' lsincantation est complexe et lourde (à moins que vous ne l'aliasiez). findne dépend pas des expansions de glob de shell, donc fonctionnera dans n'importe quel shell. findest également beaucoup plus flexible, je peux obtenir une liste récursive de tous les fichiers, ou peut-être de tous les répertoires, ou peut-être que je veux une liste de tous les fichiers xml, ou tous les fichiers modifiés au cours de la dernière semaine. Tout cela est possible avec find, mais pas facilement avec ls.
Matthew Scharley
12
J'ai dû utiliser à find "`pwd`" -name .htaccesscause des espaces dans les noms de répertoires
Paulo Casaretto
Je ne comprends pas, cette commande ne me donne pas le chemin absolu du fichier I, tandis que d'autres réponses en bas de la liste font le travail.
Bjørn Otto Vasbotten
202
readlink -f filename 

donne le chemin absolu complet. mais si le fichier est un lien symbolique, vous obtiendrez le nom résolu final.

balki
la source
8
Agréable. Ne fonctionne pas sur la variante BSD de readlink (c'est-à-dire Mac). J'utilise gnucoreutils sur mac. Et donc peut utiliser greadlink qui fonctionne avec la solution ci-dessus.
sheki
12
Pas de go sur Mac OS X.
Andrew Lazarus
1
@AndrewLazarus - Pour Mac OS X, utilisez realpathplutôt
cz
si vous installez les outils bash via brew install coreutils, alors l'exécutable sera installé en tant que/usr/local/opt/coreutils/libexec/gnubin/readlink
redolent
121

Utilisez ceci pour les répertoires (l' /after **est nécessaire dans bash pour le limiter aux répertoires):

ls -d -1 "$PWD/"**/

ceci pour les fichiers et répertoires directement sous le répertoire courant, dont les noms contiennent un .:

ls -d -1 "$PWD/"*.*

ceci pour tout:

ls -d -1 "$PWD/"**/*

Tiré d'ici http://www.zsh.org/mla/users/2002/msg00033.html

En bash, **est récursif si vous activez shopt -s globstar.

user431529
la source
1
ls -d -1 $ PWD / ** / * ne récurrente pas. J'aimerais pouvoir reprendre mon +1. Vous pouvez le faire ** pour chaque profondeur que vous devez parcourir.
user606723
4
L'opérateur ** est un opérateur de globalisation récursif. Si vous utilisez la commande dans un shell qui la prend en charge (comme zsh), elle fonctionnera correctement.
zebediah49
ls -d1 "$ PWD /"{*,.*} pour également attraper les fichiers cachés (point). Pour moi, la version récursive de la réponse n'a pas ajouté le chemin absolu aux fichiers dans les sous-dossiers.
Zael
Je pense que je vais devoir utiliser find ...
J'obtiens
30

Vous pouvez utiliser

find $PWD 

en bash

Vinko Vrsalovic
la source
3
Cela donnera également le chemin du répertoire courant, ainsi que tous les fichiers et répertoires en dessous. Ce n'est probablement pas ce que les gens recherchent.
Bill
18
ls -d "$PWD/"*

Cela ne regarde que dans le répertoire courant . Il cite "$ PWD" au cas où il contiendrait des espaces.

Ai-je
la source
C'est toujours une réponse très valable, mais il serait bon d'inclure l'information que cela ne fonctionne pas récursivement (ce que je cherchais en fait!)
bbbco
1
Pour une utilisation récursive: trouver. -exec ls -ld $ PWD / {} \;
Apprenant
10

Commander: ls -1 -d "$PWD/"*

Cela donnera les chemins absolus du fichier comme ci-dessous.

[root@kubenode1 ssl]# ls -1 -d "$PWD/"*
/etc/kubernetes/folder/file-test-config.txt
/etc/kubernetes/folder/file-test.txt
/etc/kubernetes/folder/file-client.txt
GSM
la source
8

C'est $PWDune bonne option par Matthew ci-dessus. Si vous souhaitez rechercher uniquement pour imprimer des fichiers, vous pouvez également ajouter l'option -type f pour rechercher uniquement les fichiers normaux. Les autres options sont "d" pour les répertoires uniquement etc. Donc dans votre cas, ce serait (si je veux rechercher uniquement les fichiers avec .c ext):

find $PWD -type f -name "*.c" 

ou si vous voulez tous les fichiers:

find $PWD -type f

Remarque: Vous ne pouvez pas créer d'alias pour la commande ci-dessus, car $ PWD est automatiquement complété dans votre répertoire personnel lorsque l'alias est défini par bash.

Gurpreet
la source
En fait, -d ne signifie pas uniquement les répertoires - cela signifie qu'il traite les répertoires comme des fichiers. Donc, si vous ls -d / home, vous reviendrez "/ home", pas une liste de ce qui est dans / home.
Travis
@Travis: il parlait de l'option de trouver, pas de ls. Dans son cas, "find / -type d" ne trouverait que les répertoires - comme il l'a dit.
oligofren
6

Si vous donnez à la commande find un chemin absolu, elle crachera les résultats avec un chemin absolu. Donc, à partir du répertoire Ken si vous deviez taper:

find /home/ken/foo/ -name bar -print    

(au lieu du chemin relatif find . -name bar -print)

Tu devrais obtenir:

/home/ken/foo/bar

Par conséquent, si vous voulez un ls -let qu'il renvoie le chemin absolu, vous pouvez simplement dire à la commande find d'exécuter un ls -lsur ce qu'il trouve.

find /home/ken/foo -name bar -exec ls -l {} ;\ 

REMARQUE: il y a un espace entre {}et;

Vous obtiendrez quelque chose comme ceci:

-rw-r--r--   1 ken admin       181 Jan 27 15:49 /home/ken/foo/bar

Si vous n'êtes pas sûr de l'emplacement du fichier, vous pouvez toujours modifier l'emplacement de recherche. Tant que le chemin de recherche commence par "/", vous obtiendrez un chemin absolu en retour. Si vous recherchez un emplacement (comme /) où vous allez obtenir beaucoup d'erreurs d'autorisation refusée, je recommanderais de rediriger l'erreur standard afin que vous puissiez réellement voir les résultats de la recherche:

find / -name bar -exec ls -l {} ;\ 2> /dev/null

( 2>est la syntaxe pour les shells Borne et Bash, mais ne fonctionnera pas avec le shell C. Cela peut aussi fonctionner dans d'autres shells, mais je sais seulement avec certitude que cela fonctionne dans Bourne et Bash).

Trudius
la source
Vous pouvez passer plusieurs arguments au même lsprocessus avec -exec ls -ld {} +. (Vous voulez probablement ne -dpas avoir le lscontenu du répertoire de la liste). Ou mieux, utilisez la fonction intégrée de find lsavec find ... name bar -ls. De plus, la syntaxe est incorrecte pour un argument par commande: vous devez citer le point-virgule à partir du shell, donc c'est le cas {} \;.
Peter Cordes
5

fd

En utilisant fd(alternative à find), utilisez la syntaxe suivante:

fd . foo -a

.est le modèle de recherche et foole répertoire racine.

Par exemple , pour lister tous les fichiers dans etcrécursive, exécutez: fd . /etc -a.

-a, --absolute-path Afficher les chemins absolus au lieu des chemins relatifs

Kenorb
la source
3

Juste une alternative à

ls -d "$PWD/"* 

pour identifier qui *est l'expansion du shell, donc

echo "$PWD/"*

ferait de même (l'inconvénient que vous ne pouvez pas utiliser -1pour séparer par de nouvelles lignes, pas par des espaces).

Marisha
la source
pouvez-vous nous en dire plus? qu'est-ce qu'une extension shell? comment utiliser -1pour séparer par lignes?
Antonio Araujo
@Antonio Araujo, l'expansion du shell est le shell (par exemple bash) remplacera * par la liste des fichiers - peut en savoir plus sur la page de manuel bash. -1 est l'option de commande ls, echo est une autre commande, il n'a pas les mêmes options.
Marisha
1
lspwd() { for i in $@; do ls -d -1 $PWD/$i; done }
rxw
la source
1

Voici un exemple qui imprime une liste sans période supplémentaire et qui montre également comment rechercher une correspondance de fichier. J'espère que cela t'aides:

find . -type f -name "extr*" -exec echo `pwd`/{} \; | sed "s|\./||"
Mike Behr
la source
1

Cela a fonctionné pour moi. Mais il n'a pas été classé par ordre alphabétique.

find "$(pwd)" -maxdepth 1

Cette commande répertorie par ordre alphabétique et répertorie également les fichiers cachés.

ls -d -1 "$PWD/".*; ls -d -1 "$PWD/"*;
Raveen Kumar
la source
1

stat

Chemin absolu d'un seul fichier:

stat -c %n "$PWD"/foo/bar
Kenorb
la source
1

Vous voudrez peut-être essayer ceci.

for name in /home/ken/foo/bar/*
do
    echo $name
done

Vous pouvez obtenir le chemin abs en utilisant la forboucle et echosimplement sans find.

fangxl mr
la source
0

Si vous avez besoin de la liste de tous les fichiers dans les répertoires actuels et sous-répertoires

find $PWD -type f

Si vous avez besoin de la liste de tous les fichiers uniquement dans le répertoire actuel

find $PWD -maxdepth 1 -type f
Thyag
la source
0

Cela donnera le chemin canonique (résoudra les liens symboliques): realpath FILENAME

Si vous voulez un chemin canonique vers le lien symbolique lui-même, alors: realpath -s FILENAME

JGurtz
la source
0

La plupart des méthodes suggérées, sinon toutes, entraînent des chemins qui ne peuvent pas être utilisés directement dans une autre commande de terminal si le chemin contient des espaces. Idéalement, les résultats auront des barres obliques ajoutées. Cela fonctionne pour moi sur macOS:

find / -iname "*SEARCH TERM spaces are okay*" -print 2>&1  | grep -v denied |grep -v permitted |sed -E 's/\ /\\ /g'
Adam
la source
-1

find / -print va faire ça

David Arno
la source
1
... malheureusement, cela fera autre chose (comme afficher "certains" autres fichiers à moins qu'ils ne soient filtrés)
DerMike
-1
ls -1 | awk  -vpath=$PWD/ '{print path$1}'
Albert
la source