web-dev-qa-db-fra.com

MATLAB dir sans '.' et '..'

la fonction dir retourne un tableau comme 

.
..
Folder1
Folder2

et à chaque fois je dois me débarrasser des 2 premiers éléments, avec des méthodes comme:

for i=1:numel(folders)
    foldername = folders(i).name;
    if foldername(1) == '.' % do nothing
            continue;
    end
    do_something(foldername)
end

et avec des boucles imbriquées, il peut en résulter beaucoup de code répété.

Alors, puis-je éviter ces "dossiers" par un moyen plus simple?

Merci pour toute aide!

Modifier:

Dernièrement, j'ai traité ce problème plus simplement, comme ceci:

for i=3:numel(folders)
    do_something(folders(i).name)
end

sans tenir compte des deux premiers éléments.

MAIS, faites attention à la réponse de @Jubobs. Faites attention aux noms de dossier commençant par un caractère désagréable dont la valeur ASCII est inférieure à .. Ensuite, la seconde méthode échouera. De plus, si elle commence par un ., la première méthode échouera :)

Donc, soit vous assurez que vous avez des noms de dossiers Nice et utilisez l'une de mes solutions simples, soit vous utilisez la solution de @Jubobs pour vous en assurer.

20
jeff

TL; DR

Faites défiler jusqu'au bas de ma réponse pour une fonction qui répertorie le contenu du répertoire sauf . et ...

Réponse détaillée

Les entrées . et .. correspondent au dossier actuel et au dossier parent, respectivement. Dans les shells * nix, vous pouvez utiliser des commandes telles que ls -lA pour tout lister sauf . et ... Malheureusement, la variable dir de MATLAB n'offre pas cette fonctionnalité.

Cependant, tout n'est pas perdu. Les éléments du tableau struct de sortie renvoyé par la fonction dir sont en réalité classés dans l'ordre lexicographique en fonction du champ name. Cela signifie que, si votre dossier MATLAB actuel contient des fichiers/dossiers commençant par un caractère de point de code ASCII inférieur à celui de l'arrêt complet (46, en décimal), alors . et .. seront pas. correspondent aux deux premiers éléments de ce tableau struct.

Voici un exemple illustratif: si votre dossier MATLAB actuel a la structure suivante (!hello et 'world étant des fichiers ou des dossiers),

.
├── !hello
└── 'world

alors vous obtenez ceci

>> f = dir;
>> for k = 1 : length(f), disp(f(k).name), end
!hello
'world
.
..

Pourquoi . et .. ne sont-ils pas les deux premières entrées, ici? Parce que le point d'exclamation et le guillemet simple ont des points de code plus petits (33 et 39, en décimal, resp.) Que ceux du point final (46, en décimal).

Je vous renvoie à ce tableau ASCII pour une liste exhaustive des caractères visibles ayant un point de code ASCII inférieur à celui de l'arrêt complet; Notez que tous ne sont pas nécessairement des caractères de nom de fichier légaux, cependant.

Une fonction personnalisée dir qui ne répertorie pas . et ..

Immédiatement après avoir appelé dir, vous pouvez toujours supprimer les deux entrées incriminées du tableau struct avant de le manipuler. De plus, pour plus de commodité, si vous souhaitez vous épargner une surcharge mentale, vous pouvez toujours écrire une fonction personnalisée dir qui fait ce que vous voulez:

function listing = dir2(varargin)

if nargin == 0
    name = '.';
elseif nargin == 1
    name = varargin{1};
else
    error('Too many input arguments.')
end

listing = dir(name);

inds = [];
n    = 0;
k    = 1;

while n < 2 && k <= length(listing)
    if any(strcmp(listing(k).name, {'.', '..'}))
        inds(end + 1) = k;
        n = n + 1;
    end
    k = k + 1;
end

listing(inds) = [];

Tester

En supposant la même structure de répertoires qu'avant, vous obtenez ce qui suit:

>> f = dir2;
>> for k = 1 : length(f), disp(f(k).name), end
!hello
'world
15
jubobs

Une solution sans boucle:

d=dir;
d=d(~ismember({d.name},{'.','..'}));
33
Tal

Si vous utilisez simplement dir pour obtenir une liste de fichiers et de répertoires, vous pouvez utiliser la fonction ls de Matlab. Sur les systèmes UNIX, cela renvoie simplement le résultat de la commande ls du shell, laquelle peut être plus rapide que d'appeler dir . Les répertoires . et .. ne seront pas affichés (à moins que votre shell ne soit configuré pour le faire). Notez également que le comportement de cette fonction est différent entre les systèmes UNIX et Windows.

Si vous souhaitez toujours utiliser dir et tester chaque nom de fichier de manière explicite, comme dans votre exemple, il est judicieux d'utiliser strcmp (ou l'une de ses relations) au lieu de == comparer des chaînes. Les éléments suivants ignoreraient tous les fichiers et dossiers cachés sur les systèmes UNIX:

listing = dir;
for i = 1:length(listing)
    if ~strcmp(listing(i).name(1),'.')
        % Do something
        ...
    end
end
3
horchler

une solution similaire à celle proposée par Tal est:

listing = dir(directoryname);
listing(1:2)=[];   % here you erase these . and .. items from listing

Il a l'avantage d'utiliser un truc très courant dans Matlab, mais suppose que vous sachiez que les deux premiers éléments de liste sont. et .. (ce que vous faites dans ce cas). Alors que la solution fournie par Tal (que je n’ai pas essayée cependant) semble trouver le. et .. les articles même s'ils ne sont pas placés aux deux premiers postes de la liste.

J'espère que cela pourra aider ;)

2
LeChat

Combinaison des solutions @jubobs et @Tal:

function d = dir2(folderPath)
% DIR2 lists the files in folderPath ignoring the '.' and '..' paths.

if nargin<1; folderPath = '.'; elseif nargin == 1

d = dir(folderPath);
d = d(~ismember({d.name},{'.','..'}));

end
1
Lionel Trebuchon

Vous pouvez également vouloir exclure d'autres fichiers en plus de supprimer les points 

d = dir('/path/to/parent/folder')
d(1:2)=[]; % removing dots 
d = d([d.isdir])    % [d.isdir] returns a logical array of 1s representing folders and 0s for other entries
0
Ahmed Abobakr