How to sort file when reading them with dir ?

조회 수: 52 (최근 30일)
Tural
Tural 2014년 12월 17일
댓글: Chandra Shekhar Lohani 2022년 11월 29일
I have list of text files , they are ordered like
  • doc_1.txt
  • doc_2.txt
  • ..
  • doc_20.txt
when I use
allFiles = dir('*.txt');
it is getting files in this order
  • doc_1.txt
  • doc_10.txt
  • doc_11.txtHow can I get these files in correct order?

채택된 답변

Stephen23
Stephen23 2014년 12월 18일
편집: Stephen23 2021년 4월 18일
You could download my FEX submission natsortfiles:
and use it to directly sort the output from DIR:
allFiles = natsortfiles(dir('*.txt'));
The function natsortfiles does not perform a naive natural-order sort, but also sorts the filenames and file extensions separately so that the file extension period character does not influence the sort output:
>> A = {'doc_10.txt'; 'doc_20.txt'; 'doc_2.txt'; 'doc_1.txt'; 'doc_11.txt'};
>> sort(A) % gives the wrong order!
ans =
'doc_1.txt'
'doc_10.txt'
'doc_11.txt'
'doc_2.txt'
'doc_20.txt'
>> natsortfiles(A) % the correct number order :)
ans =
'doc_1.txt'
'doc_2.txt'
'doc_10.txt'
'doc_11.txt'
'doc_20.txt'
  댓글 수: 3
Farid
Farid 2021년 3월 26일
편집: Farid 2021년 3월 26일
This saved my life
Thanks
Chandra Shekhar Lohani
Chandra Shekhar Lohani 2022년 11월 29일
Thanks @Stephen23 , this function file worked for me with .csv data .

댓글을 달려면 로그인하십시오.

추가 답변 (4개)

per isakson
per isakson 2014년 12월 17일
편집: per isakson 2014년 12월 17일
  댓글 수: 2
Tural
Tural 2014년 12월 17일
I can't use external functions ,is there any other way of doing that?
per isakson
per isakson 2014년 12월 17일
편집: per isakson 2014년 12월 18일
"[...] external functions" &nbsp why is that? &nbsp AFAIK: The alternative is to make your own function (or script). Both these FEX-contributions shows how to do that. They are well documented.

댓글을 달려면 로그인하십시오.


Andrei Bobrov
Andrei Bobrov 2014년 12월 18일
n = dir('doc_*.txt');
n1 = {n.name};
z = regexp(n1,'(?<=doc_)\d*(?=\.txt)','match');
z1 = str2double(cat(1,z{:}));
[~,ii] = sort(z1);
n01 = n1(ii);
z2 = z1(ii);
lga = floor(log10(z2)) + 1;
ml = max(lga);
ptr = ['doc_%0',num2str(ml),'d.txt'];
p = z1(ii);
k = lga < ml;
p1 = p(k);
n02 = n01(k);
if any(k)
for jj = 1:numel(p1)
movefile(n02{jj},sprintf(ptr,p1(jj)));
end
end

Thorsten
Thorsten 2014년 12월 18일
편집: Thorsten 2014년 12월 18일
Convert each filename to the corresponding number (strip leading doc_ and trailing .txt, then use double); next, sort the numbers and get the second output of sort, ind; finally use ind to re-order your filenames.
  댓글 수: 1
Stephen23
Stephen23 2014년 12월 18일
편집: Stephen23 2017년 8월 7일
As long as there is one (and only one) number per filename, and it is in exactly the same position in each filename...

댓글을 달려면 로그인하십시오.


Steve Chavez
Steve Chavez 2017년 3월 21일
편집: Steve Chavez 2017년 3월 21일
Maybe you could use the names of the files
  • Choose the order from the name to obtain indexes and then use the indexes to sort the list.
As an example: The names of the variables were chosen assuming that the number in the txts represent days.
Use dir to obtain a list into a struct
list=dir('*.txt')
Convert the struct to cell array
listcell=struct2cell(list)
[a b]=size(listcell)
Create a cell array
dia_string=cell(b,1)
A simple loop to obtain the order (order of days) from the names. If nombre is 'doc_20.txt' nombre(5:6) is equal to 20
for k=1:b
nombre=listcell{1,k};
dia_string{k}=nombre(5:6);
end
Use sort and save the index
[diaorden ind]=sort(dia_string);
Use the index in the cell array
list_2=list(ind) % list_2 is the list ordered as expected
  댓글 수: 1
Stephen23
Stephen23 2017년 3월 21일
편집: Stephen23 2017년 3월 22일
@Steve Chavez: the original question lists some example filenames:
doc_1.txt
doc_10.txt
doc_11.txt
Notice that the number of digit characters is not constant: in some cases one, some two, and perhaps more. Currently your answer takes a fixed number of characters (two) from a fixed location in the string, which means that it will give incorrect sort orders for any numbers with not-two digits, and that if the number is located elsewhere in the string the output will be rubbish. So it is not a very general solution.
However note also that if the files were named with constant-width numbers, as your answer uses, then there is no point in this answer (or any of the answers) because then a simple sort gives the correct output. Compare your answer:
>> C = {'doc_99.m','doc_10.m','doc_50.m','doc_01.m'};
>> [a,b]=size(C);
>> dia_string=cell(b,1);
>> for k=1:b, nombre=C{1,k}; dia_string{k}=nombre(5:6); end
>> [diaorden,ind]=sort(dia_string);
>> C(ind)
ans =
'doc_01.m' 'doc_10.m' 'doc_50.m' 'doc_99.m'
which gives exactly the same answer as simply calling sort:
>> sort(C)
ans =
'doc_01.m' 'doc_10.m' 'doc_50.m' 'doc_99.m'

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Shifting and Sorting Matrices에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by