복붙노트

[HADOOP] hadoop hdfs에있는 디렉토리와 서브 디렉토리에있는 모든 파일을 나열하는 법

HADOOP

hadoop hdfs에있는 디렉토리와 서브 디렉토리에있는 모든 파일을 나열하는 법

두 개의 하위 폴더가있는 hdfs 폴더가 있습니다. 각 하위 폴더에는 약 30 개의 하위 폴더가 있습니다. 마지막으로 각 하위 폴더에는 xml 파일이 들어 있습니다. 기본 폴더의 경로 만 제공하는 모든 xml 파일을 나열하고 싶습니다. 로컬에서는 아파치 commons-io의 FileUtils.listFiles ()를 사용하여이 작업을 수행 할 수 있습니다. 나는 이것을 시도했다.

FileStatus[] status = fs.listStatus( new Path( args[ 0 ] ) );

그러나 두 개의 첫 번째 하위 폴더 만 나열되며 더 이상 진행되지 않습니다. hadoop에서이 작업을 수행 할 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.FileSystem 객체를 사용하고 결과 FileStatus 객체에 대한 일부 논리를 수행하여 수동으로 하위 디렉토리로 재귀해야합니다.

    FileSystem 객체를 사용하고 결과 FileStatus 객체에 대한 일부 논리를 수행하여 수동으로 하위 디렉토리로 재귀해야합니다.

    또한 PathFilter를 적용하여 listStatus (Path, PathFilter) 메서드를 사용하여 XML 파일 만 반환 할 수도 있습니다

    hadoop FsShell 클래스는 hadoop fs -lsr 명령에 대한 예제를 가지고 있습니다. 이것은 재귀적인 ls입니다 - 590 행 주위의 소스를 봅니다 (재귀 단계는 635 행에서 트리거됩니다)

  2. ==============================

    2.hadoop 2. * API를 사용하는 경우보다 세련된 솔루션이 있습니다.

    hadoop 2. * API를 사용하는 경우보다 세련된 솔루션이 있습니다.

        Configuration conf = getConf();
        Job job = Job.getInstance(conf);
        FileSystem fs = FileSystem.get(conf);
    
        //the second boolean parameter here sets the recursion to true
        RemoteIterator<LocatedFileStatus> fileStatusListIterator = fs.listFiles(
                new Path("path/to/lib"), true);
        while(fileStatusListIterator.hasNext()){
            LocatedFileStatus fileStatus = fileStatusListIterator.next();
            //do stuff with the file like ...
            job.addFileToClassPath(fileStatus.getPath());
        }
    
  3. ==============================

    3.이것을 시도해 봤니?

    이것을 시도해 봤니?

    import java.io.*;
    import java.util.*;
    import java.net.*;
    import org.apache.hadoop.fs.*;
    import org.apache.hadoop.conf.*;
    import org.apache.hadoop.io.*;
    import org.apache.hadoop.mapred.*;
    import org.apache.hadoop.util.*;
    
    public class cat{
        public static void main (String [] args) throws Exception{
            try{
                FileSystem fs = FileSystem.get(new Configuration());
                FileStatus[] status = fs.listStatus(new Path("hdfs://test.com:9000/user/test/in"));  // you need to pass in your hdfs path
    
                for (int i=0;i<status.length;i++){
                    BufferedReader br=new BufferedReader(new InputStreamReader(fs.open(status[i].getPath())));
                    String line;
                    line=br.readLine();
                    while (line != null){
                        System.out.println(line);
                        line=br.readLine();
                    }
                }
            }catch(Exception e){
                System.out.println("File not found");
            }
        }
    }
    
  4. ==============================

    4.

    /**
     * @param filePath
     * @param fs
     * @return list of absolute file path present in given path
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static List<String> getAllFilePath(Path filePath, FileSystem fs) throws FileNotFoundException, IOException {
        List<String> fileList = new ArrayList<String>();
        FileStatus[] fileStatus = fs.listStatus(filePath);
        for (FileStatus fileStat : fileStatus) {
            if (fileStat.isDirectory()) {
                fileList.addAll(getAllFilePath(fileStat.getPath(), fs));
            } else {
                fileList.add(fileStat.getPath().toString());
            }
        }
        return fileList;
    }
    

    빠른 예 : 다음과 같은 파일 구조가 있다고 가정 해보십시오.

    a  ->  b
       ->  c  -> d
              -> e 
       ->  d  -> f
    

    위의 코드를 사용하면 다음을 얻을 수 있습니다.

    a/b
    a/c/d
    a/c/e
    a/d/f
    

    리프 (예 : fileNames) 만 원하면 else 블록에 다음 코드를 사용하십시오.

     ...
        } else {
            String fileName = fileStat.getPath().toString(); 
            fileList.add(fileName.substring(fileName.lastIndexOf("/") + 1));
        }
    

    이것은 줄 것이다 :

    b
    d
    e
    f
    
  5. ==============================

    5.이제는 Spark를 사용하여 다른 접근 방식 (예 : Hadoop MR)보다 빠르고 똑같이 수행 할 수 있습니다. 다음은 코드 스 니펫입니다.

    이제는 Spark를 사용하여 다른 접근 방식 (예 : Hadoop MR)보다 빠르고 똑같이 수행 할 수 있습니다. 다음은 코드 스 니펫입니다.

    def traverseDirectory(filePath:String,recursiveTraverse:Boolean,filePaths:ListBuffer[String]) {
        val files = FileSystem.get( sparkContext.hadoopConfiguration ).listStatus(new Path(filePath))
                files.foreach { fileStatus => {
                    if(!fileStatus.isDirectory() && fileStatus.getPath().getName().endsWith(".xml")) {                
                        filePaths+=fileStatus.getPath().toString()      
                    }
                    else if(fileStatus.isDirectory()) {
                        traverseDirectory(fileStatus.getPath().toString(), recursiveTraverse, filePaths)
                    }
                }
        }   
    }
    
  6. ==============================

    6.다음은 특정 HDFS 디렉토리의 파일 수를 계산하는 코드 단편입니다 (특정 ETL 코드에서 사용할 감속기의 수를 결정하는 데이 번호를 사용했습니다). 필요에 맞게 쉽게 수정할 수 있습니다.

    다음은 특정 HDFS 디렉토리의 파일 수를 계산하는 코드 단편입니다 (특정 ETL 코드에서 사용할 감속기의 수를 결정하는 데이 번호를 사용했습니다). 필요에 맞게 쉽게 수정할 수 있습니다.

    private int calculateNumberOfReducers(String input) throws IOException {
        int numberOfReducers = 0;
        Path inputPath = new Path(input);
        FileSystem fs = inputPath.getFileSystem(getConf());
        FileStatus[] statuses = fs.globStatus(inputPath);
        for(FileStatus status: statuses) {
            if(status.isDirectory()) {
                numberOfReducers += getNumberOfInputFiles(status, fs);
            } else if(status.isFile()) {
                numberOfReducers ++;
            }
        }
        return numberOfReducers;
    }
    
    /**
     * Recursively determines number of input files in an HDFS directory
     *
     * @param status instance of FileStatus
     * @param fs instance of FileSystem
     * @return number of input files within particular HDFS directory
     * @throws IOException
     */
    private int getNumberOfInputFiles(FileStatus status, FileSystem fs) throws IOException  {
        int inputFileCount = 0;
        if(status.isDirectory()) {
            FileStatus[] files = fs.listStatus(status.getPath());
            for(FileStatus file: files) {
                inputFileCount += getNumberOfInputFiles(file, fs);
            }
        } else {
            inputFileCount ++;
        }
    
        return inputFileCount;
    }
    
  7. ==============================

    7.Radu Adrian Moldovan에게 제안에 감사드립니다.

    Radu Adrian Moldovan에게 제안에 감사드립니다.

    다음은 대기열을 사용하는 구현입니다.

    private static List<String> listAllFilePath(Path hdfsFilePath, FileSystem fs)
    throws FileNotFoundException, IOException {
      List<String> filePathList = new ArrayList<String>();
      Queue<Path> fileQueue = new LinkedList<Path>();
      fileQueue.add(hdfsFilePath);
      while (!fileQueue.isEmpty()) {
        Path filePath = fileQueue.remove();
        if (fs.isFile(filePath)) {
          filePathList.add(filePath.toString());
        } else {
          FileStatus[] fileStatus = fs.listStatus(filePath);
          for (FileStatus fileStat : fileStatus) {
            fileQueue.add(fileStat.getPath());
          }
        }
      }
      return filePathList;
    }
    
  8. ==============================

    8.재귀 적 접근법 (heap issues)을 사용하지 마라. :) 대기열을 사용하다

    재귀 적 접근법 (heap issues)을 사용하지 마라. :) 대기열을 사용하다

    queue.add(param_dir)
    while (queue is not empty){
    
      directory=  queue.pop
     - get items from current directory
     - if item is file add to a list (final list)
     - if item is directory => queue.push
    }
    

    그거 쉽지, 즐겨라!

  9. ==============================

    9.재귀 적 접근과 비 재귀 적 접근 모두를위한 코드 스 니펫 :

    재귀 적 접근과 비 재귀 적 접근 모두를위한 코드 스 니펫 :

    //helper method to get the list of files from the HDFS path
    public static List<String>
        listFilesFromHDFSPath(Configuration hadoopConfiguration,
                              String hdfsPath,
                              boolean recursive) throws IOException,
                                            IllegalArgumentException
    {
        //resulting list of files
        List<String> filePaths = new ArrayList<String>();
    
        //get path from string and then the filesystem
        Path path = new Path(hdfsPath);  //throws IllegalArgumentException
        FileSystem fs = path.getFileSystem(hadoopConfiguration);
    
        //if recursive approach is requested
        if(recursive)
        {
            //(heap issues with recursive approach) => using a queue
            Queue<Path> fileQueue = new LinkedList<Path>();
    
            //add the obtained path to the queue
            fileQueue.add(path);
    
            //while the fileQueue is not empty
            while (!fileQueue.isEmpty())
            {
                //get the file path from queue
                Path filePath = fileQueue.remove();
    
                //filePath refers to a file
                if (fs.isFile(filePath))
                {
                    filePaths.add(filePath.toString());
                }
                else   //else filePath refers to a directory
                {
                    //list paths in the directory and add to the queue
                    FileStatus[] fileStatuses = fs.listStatus(filePath);
                    for (FileStatus fileStatus : fileStatuses)
                    {
                        fileQueue.add(fileStatus.getPath());
                    } // for
                } // else
    
            } // while
    
        } // if
        else        //non-recursive approach => no heap overhead
        {
            //if the given hdfsPath is actually directory
            if(fs.isDirectory(path))
            {
                FileStatus[] fileStatuses = fs.listStatus(path);
    
                //loop all file statuses
                for(FileStatus fileStatus : fileStatuses)
                {
                    //if the given status is a file, then update the resulting list
                    if(fileStatus.isFile())
                        filePaths.add(fileStatus.getPath().toString());
                } // for
            } // if
            else        //it is a file then
            {
                //return the one and only file path to the resulting list
                filePaths.add(path.toString());
            } // else
    
        } // else
    
        //close filesystem; no more operations
        fs.close();
    
        //return the resulting list
        return filePaths;
    } // listFilesFromHDFSPath
    
  10. from https://stackoverflow.com/questions/11342400/how-to-list-all-files-in-a-directory-and-its-subdirectories-in-hadoop-hdfs by cc-by-sa and MIT license