How to get the list of files in a directory in a shell script?
У некоторых пользователей, при работе на компьютере, возникает необходимость получить список файлов в папке. Такой список может быть нужен для разных целей: для каталогизации файлов в папках, для сравнения содержимого в папках, для того, чтобы составить список фильмов, музыкальных композиций, электронных книг и т. п.
Во многих случаях, количество файлов может быть очень большим, поэтому вручную составить полный список находящихся в папке файлов будет проблематично. Предположим, в папке на вашем компьютере хранится электронная библиотека, или вы имеете большое собрание фильмов. Даже увлеченному человеку запомнить все содержимое папки или диска будет нереально.
Выходом из этой ситуации будет создание списка файлов, находящихся в данной папке, а потом сохранение этого списка в текстовый файл. В дальнейшем, полученный список можно будет отредактировать так, как это будет необходимо.
Например, у меня на внешних жестких дисках, каждый из которых имеет размер в несколько терабайт, хранится большая коллекция фильмов, которые я собирал несколько лет. Мне, конечно, тяжело запомнить все названия фильмов, которые хранятся на жестких дисках.
Встречая в интернете какой-либо фильм, имея у себя список файлов в папке, я могу легко проверить, есть ли такой фильм у меня в коллекции, или я встретил новый фильм. Поэтому я приступил к поиску решения данного вопроса.
В итоге, я нашел несколько простых вариантов решения этой проблемы. Создать список файлов в папке можно разными способами: при помощи командной строки, при помощи файла, который имеет расширение «.bat», при помощи специальных программ, сохранить список в браузере.
If the path is passed without ending separator, a separator will be appended to the path. For the extension, if an empty string is inputted then the function will return any file that does not have an extension in its name. If a single star was inputted than all files in the directory will be returned. If e length is greater than 0 but is not a single * then a dot will be prepended to e if e had not contained a dot at the zero position.
For a returning value. If a zero-length map is returned then nothing was found but the directory was open okay. If index 999 is available from the return value but the map size is only 1 then that meant there was a problem with opening the directory path.
Note that for efficiency, this function can be split into 3 smaller functions. On top of that, you can create a caller function that will detect which function it is going to call based on the input. Why is that more efficient? Said if you are going to grab everything that is a file, doing that method the subfunction that built for grabbing all the files will just grab all that are files and does not need to evaluate any other unnecessary condition everytime it found a file.
That would also apply to when you grab files that do not have an extension. A specific built function for that purpose would only evaluate for weather if the object found is a file and then whether or not if the name of the file has a dot in it.
The saving may not be much if you only read directories with not so much files. But if you are reading a mass amount of directory or if the directory has couple hundred thousands of files, it could be a huge saving.
#include <stdio.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include <map>
std::map<int, std::string> getFile(std::string p, std::string e = "", unsigned char s = '/'){ if ( p.size() > 0 ){ if (p.back() != s) p += s; } if ( e.size() > 0 ){ if ( e.at(0) != '.' && !(e.size() == 1 && e.at(0) == '*') ) e = "." + e; } DIR *dir; struct dirent *ent; struct stat sb; std::map<int, std::string> r = {{999, "FAILED"}}; std::string temp; int f = 0; bool fd; if ( (dir = opendir(p.c_str())) != NULL ){ r.erase (999); while ((ent = readdir (dir)) != NULL){ temp = ent->d_name; fd = temp.find(".") != std::string::npos? true : false; temp = p + temp; if (stat(temp.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)){ if ( e.size() == 1 && e.at(0) == '*' ){ r[f] = temp; f++; } else { if (e.size() == 0){ if ( fd == false ){ r[f] = temp; f++; } continue; } if (e.size() > temp.size()) continue; if ( temp.substr(temp.size() - e.size()) == e ){ r[f] = temp; f++; } } } } closedir(dir); return r; } else { return r; }
}
void printMap(auto &m){ for (const auto &p : m) { std::cout << "m[" << p.first << "] = " << p.second << std::endl; }
}
int main(){ std::map<int, std::string> k = getFile("./", ""); printMap(k); return 0;
} 
Когда ко мне обратились с вопросом о том, как быстро вывести список файлов в текстовый файл, я понял, что ответа я не знаю. Хотя задача, как оказалось, достаточно часто встречающаяся. Это может потребоваться для передачи списка файлов специалисту (для решения какой-то проблемы), самостоятельного ведения журнала содержимого папок и других целей.
Решено было устранить пробел и подготовить инструкцию на эту тему, в которой будет показано, как получить список файлов (и вложенных папок) в папке Windows средствами командной строки, а также о том, как автоматизировать этот процесс, если задача возникает часто.
Получение текстового файла с содержимым папки в командной строке

Сначала о том, как сделать текстовый документ, содержащий список файлов в нужной папке, вручную.
- Запустите командную строку от имени администратора.
- Введите cd
x:\
folder\
где x:\folder\ — полный путь к папке, список файлов из которой нужно получить. Нажмите Enter. - Введите команду dir /
a /-
p /
o:
gen >
files.
txt
(где files.txt — текстовый файл, в котором будет сохранен список файлов). Нажмите Enter. - Если использовать команду с параметром /b ( dir /
a /
b /-
p /
o:
gen >
files.
txt
), то в полученном списке будет отсутствовать любая дополнительная информация о размерах файлов или дате создания — только список имен.
Готово. В результате будет создан текстовый файл, содержащий необходимую информацию. В команде выше, данный документ сохраняется в той же папке, список файлов из которой требуется получить. Можно также убрать вывод в текстовый файл, в этом случае список будет отображаться только в командной строке.

Кроме этого, для пользователей русскоязычной версии Windows следует учитывать то, что файл сохраняется в кодировке Windows 866, то есть в обычном блокноте вместо русских символов вы увидите иероглифы (но можно использовать альтернативный текстовый редактор для просмотра, например, Sublime Text).
Получаем список файлов с помощью Windows PowerShell
Вы также можете получить список файлов в папке используя команды Windows PowerShell. Если вы хотите сохранить список в файл, то запустите PowerShell от имени администратора, если просто просмотреть в окне — достаточно простого запуска.

- Get-Childitem -Path C:\Folder — вывод списка всех файлов и папок, находящихся в папке Folder на диске C в окне Powershell.
- Get-Childitem -Path C:\Folder | Out-File C:\Files.txt — создание текстового файла Files.txt со списком файлов в папке Folder.
- Добавление параметра -Recurse к первой описанной команде выводит в списке также содержимое всех вложенных папок.
- Параметры -File и -Directory позволяют получить список только файлов или только папок соответственно.

Выше перечислены далеко не все параметры Get-Childitem, но в рамках описываемой в этом руководстве задачи, думаю, их будет достаточно.
Утилита Microsoft Fix it для печати содержимого папки
На странице https://support.microsoft.com/ru-ru/kb/321379
присутствует утилита Microsoft Fix It, добавляющая в контекстное меню проводника пункт «Print Directory Listing», выводящий список файлов в папке на печать.

Несмотря на то, что программа предназначена только для Windows XP, Vista и Windows 7, она успешно сработала и в Windows 10, достаточно было запустить ее в режиме совместимости.
Дополнительно, на той же странице показан порядок ручного добавления команды вывода списка файлов в проводник, при этом вариант для Windows 7 подойдет и для Windows 8.1 и 10. А если вам не требуется вывод на печать, вы можете немного подправить предлагаемые Microsoft команды, удалив параметр /p в третьей строке и полностью убрав четвертую.
Capture the output of any command into a bash indexed array, with elements separated by the newline char (\n)
However,
$search_dir
contains many files with whitespaces in their names. In that case, this script does not run as expected.
This is solved by telling bash to separate elements in the string based on the newline char \n
instead of the space char–which is the default IFS
(Internal Field Separator–see The Meaning of IFS
in Bash Scripting
) variable used by bash. To do this, I recommend using the mapfile
command.
The bash script static code analyzer tool named shellscript
recommends using mapfile
or read -r
whenever you want to read in a string into a bash array, separating elements based on the newline char ( \n
). See: https://github.com/koalaman/shellcheck/wiki/SC2206
.
(Back to my original answer:)
Here is how to convert a newline-separated string into a regular bash “indexed” array with the mapfile
command
.
# Capture the output of `ls -1` into a regular bash "indexed" array.
# - includes both files AND directories!
mapfile -t allfilenames_array <<< "$(ls -1)"
# Capture the output of `find` into a regular bash "indexed" array
# - includes directories ONLY!
# Note: for other `-type` options, see `man find`.
mapfile -t dirnames_array \ <<< "$(find . -mindepth 1 -maxdepth 1 -type d | sort -V)" - We use
ls -1
(that’s a “dash numeral_one”) in order to put each filename on its own line, thereby separating them all by the newline\n
char. - If you’d like to Google it,
<<<
is called a “here string” in bash. - See
mapfile --help
, orhelp mapfile
, for help.
Full code example:
From file array_list_all_files_and_directories.sh
in my eRCaGuy_hello_world
repo:
echo "Output of 'ls -1'"
echo "-----------------"
ls -1
echo ""
# Capture the output of `ls -1` into a regular bash "indexed" array.
# - includes both files AND directories!
mapfile -t allfilenames_array <<< "$(ls -1)"
# Capture the output of `find` into a regular bash "indexed" array
# - includes directories ONLY!
# Note: for other `-type` options, see `man find` and see my answer here:
# https://stackoverflow.com/a/71345102/4561887
mapfile -t dirnames_array \ <<< "$(find . -mindepth 1 -maxdepth 1 -type d | sort -V)"
# Get the number of elements in each array
allfilenames_array_len="${#allfilenames_array[@]}"
dirnames_array_len="${#dirnames_array[@]}"
# 1. Now manually print all elements in each array
echo "All filenames (files AND dirs) (count = $allfilenames_array_len):"
for filename in "${allfilenames_array[@]}"; do echo " $filename"
done
echo "Dirnames ONLY (count = $dirnames_array_len):"
for dirname in "${dirnames_array[@]}"; do # remove the `./` from the beginning of each dirname dirname="$(basename "$dirname")" echo " $dirname"
done
echo ""
# OR, 2. manually print the index number followed by all elements in the array
echo "All filenames (files AND dirs) (count = $allfilenames_array_len):"
for i in "${!allfilenames_array[@]}"; do printf " %3i: %s\n" "$i" "${allfilenames_array["$i"]}"
done
echo "Dirnames ONLY (count = $dirnames_array_len):"
for i in "${!dirnames_array[@]}"; do # remove the `./` from the beginning of each dirname dirname="$(basename "${dirnames_array["$i"]}")" printf " %3i: %s\n" "$i" "$dirname"
done
echo "" eRCaGuy_hello_world/python$ ../bash/array_list_all_files_and_directories.sh
Output of 'ls -1'
-----------------
autogenerate_c_or_cpp_code.py
autogenerated
auto_white_balance_img.py
enum_practice.py
raw_bytes_practice.py
slots_practice
socket_talk_to_ethernet_device.py
textwrap_practice_1.py
yaml_import
All filenames (files AND dirs) (count = 9): autogenerate_c_or_cpp_code.py autogenerated auto_white_balance_img.py enum_practice.py raw_bytes_practice.py slots_practice socket_talk_to_ethernet_device.py textwrap_practice_1.py yaml_import
Dirnames ONLY (count = 3): autogenerated slots_practice yaml_import
All filenames (files AND dirs) (count = 9): 0: autogenerate_c_or_cpp_code.py 1: autogenerated 2: auto_white_balance_img.py 3: enum_practice.py 4: raw_bytes_practice.py 5: slots_practice 6: socket_talk_to_ethernet_device.py 7: textwrap_practice_1.py 8: yaml_import
Dirnames ONLY (count = 3): 0: autogenerated 1: slots_practice 2: yaml_import Программа DirLister для получения списка файлов
Вы можете создать список файлов расположенных в папке, при помощи бесплатной программы DirLister. Эта крошечная программа не требует установки на компьютер. После загрузки программы на свой компьютер, распакуйте архив с программой.
Для запуска программы, откройте папку с программой, а потом кликните по приложению DirLister.
В окне программы DirLister, в разделе «Directory To Scan», при помощи кнопки «Open», вам нужно будет выбрать папку для сканирования.
Вы можете уточнить критерии поиска файлов по маске «*.*», выбрав нужное имя или тип файла («TXT», «Excel», «HTML» и т. д.). После выбора необходимых настроек, нажмите на кнопку «Make List».

После завершения сканирования в левом нижнем углу программы будет выведена информация об успешном завершении создания списка файлов: «All file processed correctly».
Программа DirLister выводит не только список файлов в данной папке, но и дает полную информацию о вложенных в эту папку файлах и папках, в том числе о размере файлов.
Preliminary notes
Although there’s a clear differentiation between file
and directory
terms in the question text, some may argue that directories are actually special filesThe statement: ” all files of a directory
” can be interpreted in two ways:All direct
(or level 1) descendants onlyAll descendants in the whole directory tree (including the ones in sub-directories)
When the question was asked, I imagine that Python 2
, was the LTS
version, however the code samples will be run by Python 3
( .5
)
(I’ll keep them as Python 2
compliant as possible; also, any code belonging to Python
that I’m going to post, is from v3.5.4
– unless otherwise specified).That has consequences related to another keyword in the question: ” add them into a list
“:In Python 3
, generator is the default behavior
>>> import sys >>> >>> sys.version '2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]' >>> m = map(lambda x: x, [1, 2, 3]) # Just a dummy lambda function >>> m, type(m) ([1, 2, 3], <type 'list'>) >>> len(m) 3>>> import sys >>> >>> sys.version '3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]' >>> m = map(lambda x: x, [1, 2, 3]) >>> m, type(m) (<map object at 0x000001B4257342B0>, <class 'map'>) >>> len(m) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'map' has no len() >>> lm0 = list(m) # Build a list from the generator >>> lm0, type(lm0) ([1, 2, 3], <class 'list'>) >>> >>> lm1 = list(m) # Build a list from the same generator >>> lm1, type(lm1) # Empty list now - generator already exhausted ([], <class 'list'>)[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q003207219]> sopr.bat ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [prompt]> [prompt]> tree /f "root_dir" Folder PATH listing for volume Work Volume serial number is 00000029 3655:6FED E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR ¦ file0 ¦ file1 ¦ +---dir0 ¦ +---dir00 ¦ ¦ ¦ file000 ¦ ¦ ¦ ¦ ¦ +---dir000 ¦ ¦ file0000 ¦ ¦ ¦ +---dir01 ¦ ¦ file010 ¦ ¦ file011 ¦ ¦ ¦ +---dir02 ¦ +---dir020 ¦ +---dir0200 +---dir1 ¦ file10 ¦ file11 ¦ file12 ¦ +---dir2 ¦ ¦ file20 ¦ ¦ ¦ +---dir20 ¦ file200 ¦ +---dir3
Solutions
Programmatic approaches
1. [Python. Docs]: os.listdir(path=’.’)
>>> import os >>> >>> root_dir = "root_dir" # Path relative to current dir (os.getcwd()) >>> >>> os.listdir(root_dir) # List all the items in root_dir ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))] # Filter items and only keep files (strip out directories) ['file0', 'file1']
A more elaborate example ( code_os_listdir.py
):
#!/usr/bin/env python
import os
import sys
from pprint import pformat as pf
def _get_dir_content(path, include_folders, recursive): entries = os.listdir(path) for entry in entries: entry_with_path = os.path.join(path, entry) if os.path.isdir(entry_with_path): if include_folders: yield entry_with_path if recursive: for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive): yield sub_entry else: yield entry_with_path
def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True): path_len = len(path) + len(os.path.sep) for item in _get_dir_content(path, include_folders, recursive): yield item if prepend_folder_name else item[path_len:]
def _get_dir_content_old(path, include_folders, recursive): entries = os.listdir(path) ret = list() for entry in entries: entry_with_path = os.path.join(path, entry) if os.path.isdir(entry_with_path): if include_folders: ret.append(entry_with_path) if recursive: ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive)) else: ret.append(entry_with_path) return ret
def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True): path_len = len(path) + len(os.path.sep) return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)]
def main(*argv): root_dir = "root_dir" ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True) lret0 = list(ret0) print("{:} {:d}\n{:s}".format(ret0, len(lret0), pf(lret0))) ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False) print("\n{:d}\n{:s}".format(len(ret1), pf(ret1)))
if __name__ == "__main__": print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) rc = main(*sys.argv[1:]) print("\nDone.\n") sys.exit(rc) There are two implementations:
One that uses generators (of course here it seems useless, since I immediately convert the result to a list)
The classic one (function names ending in _old
)
Recursion is used (to get into subdirectories)
For each implementation there are two functions:
One that starts with an underscore
( _
): “private” (should not be called directly) – that does all the workThe public one (wrapper over previous): it just strips off the initial path (if required) from the returned entries. It’s an ugly implementation, but it’s the only idea that I could come with at this point
In terms of performance, generators are generally a little bit faster (considering both creation
and iteration
times), but I didn’t test them in recursive functions, and also I am iterating inside the function over inner generators – don’t know how performance friendly is thatPlay with the arguments to get different results
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.05.04_test0\Scripts\python.exe" ".\code_os_listdir.py" Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] 064bit on win32 <generator object get_dir_content at 0x000002C080418F68> 22 ['root_dir\\dir0', 'root_dir\\dir0\\dir00', 'root_dir\\dir0\\dir00\\dir000', 'root_dir\\dir0\\dir00\\dir000\\file0000', 'root_dir\\dir0\\dir00\\file000', 'root_dir\\dir0\\dir01', 'root_dir\\dir0\\dir01\\file010', 'root_dir\\dir0\\dir01\\file011', 'root_dir\\dir0\\dir02', 'root_dir\\dir0\\dir02\\dir020', 'root_dir\\dir0\\dir02\\dir020\\dir0200', 'root_dir\\dir1', 'root_dir\\dir1\\file10', 'root_dir\\dir1\\file11', 'root_dir\\dir1\\file12', 'root_dir\\dir2', 'root_dir\\dir2\\dir20', 'root_dir\\dir2\\dir20\\file200', 'root_dir\\dir2\\file20', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1'] 11 ['dir0\\dir00\\dir000\\file0000', 'dir0\\dir00\\file000', 'dir0\\dir01\\file010', 'dir0\\dir01\\file011', 'dir1\\file10', 'dir1\\file11', 'dir1\\file12', 'dir2\\dir20\\file200', 'dir2\\file20', 'file0', 'file1'] Done.
2. [Питон. Документы]: os.scandir(path=’.’)
Возвращает итератор os. ДирЭнтри
объекты, соответствующие записям в каталоге, заданном путем
. Записи выдаются в произвольном порядке, а специальные записи'.'
и'..'
не включены.Использование scandir()
вместо listdir()
может значительно повысить производительность кода, которому также требуется информация о типе файла или атрибуте файла, поскольку os. Режиссёр
объекты раскрывают эту информацию, если операционная система предоставляет ее при сканировании каталога. Все ос. ДирЭнтри
методы могут выполнять системный вызов, но is_dir()
и is_file()
обычно требуется только системный вызов для символических ссылок; ок. DirEntry.stat()
всегда требует системного вызова в Unix, но требует его только для символических ссылок в Windows.
>>> import os >>> >>> root_dir = os.path.join(".", "root_dir") # Explicitly prepending current directory >>> root_dir '.\\root_dir' >>> >>> scandir_iterator = os.scandir(root_dir) >>> scandir_iterator <nt.ScandirIterator object at 0x00000268CF4BC140> >>> [item.path for item in scandir_iterator] ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1'] >>> >>> [item.path for item in scandir_iterator] # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension) [] >>> >>> scandir_iterator = os.scandir(root_dir) # Reinitialize the generator >>> for item in scandir_iterator : ... if os.path.isfile(item.path): ... print(item.name) ... file0 file1
Аналогично os.listdir
Но он также более гибкий (и предлагает больше функций), больше Python
ic (а в некоторых случаях и быстрее)
3. [Питон. Документы]: os.walk(top, topdown=True, onerror=None, followlinks=False)
Создание имен файлов в дереве каталогов путем обхода дерева сверху вниз или снизу вверх. Для каждого каталога в дереве с корнем в каталоге вверху
(в том числе топ
сам), он дает 3-кортеж (dirpath
,dirnames
,filenames
).
>>> import os >>> >>> root_dir = os.path.join(os.getcwd(), "root_dir") # Specify the full path >>> root_dir 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir' >>> >>> walk_generator = os.walk(root_dir) >>> root_dir_entry = next(walk_generator) # First entry corresponds to the root dir (passed as an argument) >>> root_dir_entry ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1']) >>> >>> root_dir_entry[1] + root_dir_entry[2] # Display dirs and files (direct descendants) in a single list ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]] # Display all the entries in the previous list by their full path ['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1'] >>> >>> for entry in walk_generator: # Display the rest of the elements (corresponding to every subdir) ... print(entry) ... ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', ['dir20'], ['file20']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20', [], ['file200']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', [], [])
Под сценами используется os.scandir
( os.listdir
на более старых ( Python
) версии)Он делает тяжелую работу, повторяясь во вложенных папках
4. [Питон. Документы]: glob.glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False)
>>> import glob, os >>> >>> wildcard_pattern = "*" >>> root_dir = os.path.join("root_dir", wildcard_pattern) # Match every file/dir name >>> root_dir 'root_dir\\*' >>> >>> glob_list = glob.glob(root_dir) >>> glob_list ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1'] >>> >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list] # Strip the dir name and the path separator from begining ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> for entry in glob.iglob(root_dir + "*", recursive=True): ... print(entry) ... root_dir\ root_dir\dir0 root_dir\dir0\dir00 root_dir\dir0\dir00\dir000 root_dir\dir0\dir00\dir000\file0000 root_dir\dir0\dir00\file000 root_dir\dir0\dir01 root_dir\dir0\dir01\file010 root_dir\dir0\dir01\file011 root_dir\dir0\dir02 root_dir\dir0\dir02\dir020 root_dir\dir0\dir02\dir020\dir0200 root_dir\dir1 root_dir\dir1\file10 root_dir\dir1\file11 root_dir\dir1\file12 root_dir\dir2 root_dir\dir2\dir20 root_dir\dir2\dir20\file200 root_dir\dir2\file20 root_dir\dir3 root_dir\file0 root_dir\file1
Для больших деревьев (особенно если рекурсивный
горит), иглоб
предпочтительнееРазрешает расширенную фильтрацию на основе имени (из-за подстановочного знака)
5. [Питон. Документы]: class pathlib. Путь (* сегменты пути)
>>> import pathlib >>> >>> root_dir = "root_dir" >>> root_dir_instance = pathlib.Path(root_dir) >>> root_dir_instance WindowsPath('root_dir') >>> root_dir_instance.name 'root_dir' >>> root_dir_instance.is_dir() True >>> >>> [item.name for item in root_dir_instance.glob("*")] # Wildcard searching for all direct descendants ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()] # Display paths (including parent) for files only ['root_dir\\file0', 'root_dir\\file1']
Это один
способ достижения нашей целиЭто ООП
стиль обработки путейПредлагает множество функций
6. [Python 2. Документы]: dircache.listdir(путь)
Питон 2
только
def listdir(path): """List directory contents, using cache.""" try: cached_mtime, list = cache[path] del cache[path] except KeyError: cached_mtime, list = -1, [] mtime = os.stat(path).st_mtime if mtime != cached_mtime: list = os.listdir(path) list.sort() cache[path] = mtime, list return list
7. Родная ОС
API
с
#!/usr/bin/env python3
import ctypes as cts
import sys
DT_DIR = 4
DT_REG = 8
class NixDirent64(cts.Structure): _fields_ = ( ("d_ino", cts.c_ulonglong), ("d_off", cts.c_longlong), ("d_reclen", cts.c_ushort), ("d_type", cts.c_ubyte), ("d_name", cts.c_char * 256), )
NixDirent64Ptr = cts.POINTER(NixDirent64)
libc = this_process = cts.CDLL(None, use_errno=True)
opendir = libc.opendir
opendir.argtypes = (cts.c_char_p,)
opendir.restype = cts.c_void_p
readdir = libc.readdir
readdir.argtypes = (cts.c_void_p,)
readdir.restype = NixDirent64Ptr
closedir = libc.closedir
closedir.argtypes = (cts.c_void_p,)
def get_dir_content(path): ret = [path, [], []] pdir = opendir(cts.create_string_buffer(path.encode())) if not pdir: print("opendir returned NULL (errno: {:d})".format(cts.get_errno())) return ret cts.set_errno(0) while True: pdirent = readdir(pdir) if not pdirent: break dirent = pdirent.contents name = dirent.d_name.decode() if dirent.d_type & DT_DIR: if name not in (".", ".."): ret[1].append(name) elif dirent.d_type & DT_REG: ret[2].append(name) if cts.get_errno(): print("readdir returned NULL (errno: {:d})".format(cts.get_errno())) closedir(pdir) return ret
def main(*argv): root_dir = "root_dir" entries = get_dir_content(root_dir) print("Entries:\n{:}".format(entries))
if __name__ == "__main__": print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) rc = main(*sys.argv[1:]) print("\nDone.\n") sys.exit(rc) Возвращает данные в os.walk
формат. Я не удосужился сделать его рекурсивным, но, начиная с существующего кода, это было бы довольно тривиальной задачей
[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q003207219]> python3.5 ./code_ctypes.py Python 3.5.10 (default, Jan 15 2022, 19:53:00) [GCC 9.3.0] 064bit on linux Entries: ['root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1']] Done.
8. [TimGolden]: win32file. FindFilesW
Получает список совпадающих имен файлов, используя Windows Unicode API. Интерфейс к функциям API FindFirstFileW/FindNextFileW/Find close.
>>> import os, win32file as wfile, win32con as wcon >>> >>> root_dir = "root_dir" >>> root_dir_wildcard = os.path.join(root_dir, "*") >>> entry_list = wfile.FindFilesW(root_dir_wildcard) >>> len(entry_list) # Don't display the whole content as it's too long 8 >>> [entry[-2] for entry in entry_list] # Only display the entry names ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [entry[-2] for entry in entry_list if entry[0] & wcon.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")] # Filter entries and only display dir names (except self and parent) ['dir0', 'dir1', 'dir2', 'dir3'] >>> >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (wcon.FILE_ATTRIBUTE_NORMAL | wcon.FILE_ATTRIBUTE_ARCHIVE)] # Only display file "full" names ['root_dir\\file0', 'root_dir\\file1']
- файл win32. FindFilesW
является частью [GitHub]: mhammond/pywin32 — расширения Python для Windows (pywin32)
, который представляет собой Python
обертка над WinAPI
с
9. Использовать некоторые (другие) 3 рд
пакет для вечеринки, который делает свое дело
Скорее всего, будет опираться на один (или несколько) из вышеперечисленных (возможно, с небольшими изменениями).
Примечания:
Код должен быть переносимым (за исключением мест, предназначенных для определенной области, которые помечены) или пересекаться:
ОС
( Никс
, Победа
, )Питон
версия (2, 3, )
Несколько стилей пути (абсолютные, относительные) использовались в вышеупомянутых вариантах, чтобы проиллюстрировать тот факт, что используемые «инструменты» гибки в этом направлении
_get_dir_content
(из точки №1.
) может быть реализован с использованием любого из этих подходов (некоторые потребуют больше работы, а некоторые меньше)- Некоторая расширенная фильтрация (вместо простого файла против
реж.
) можно сделать: например.
include_folders
аргумент может быть заменен другим (например, filter_func
), которая будет функцией, принимающей путь в качестве аргумента:filter_func=lambda x: True
(это ничего не удаляет) и внутри _get_dir_content
что-то вроде:if not filter_func(entry_with_path): continue
(если функция дает сбой для одной записи, она будет пропущена), но чем сложнее становится код, тем дольше он будет выполняться
- Некоторая расширенная фильтрация (вместо простого файла против
Другие подходы:
1. Используйте Python
только в обертке
Все делается по другой технологии
Эта технология вызвана из Python
Использовать Python
(или любой язык программирования в этом отношении) для выполнения Shell
команды (и анализировать их выходные данные)Некоторые считают это ловким хаком
Я считаю это скорее хромым обходным путем ( gainarie
), как действие как таковое
выполняется из ракушки
( Команд
в данном случае) и, таким образом, не имеет ничего общего с Python
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.05.04_test0\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")" dir0 dir1 dir2 dir3 file0 file1
[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q003207219]> python3.5 -c "import os;os.system(\"ls root_dir\")" dir0 dir1 dir2 dir3 file0 file1
Как правило, этого подхода следует избегать, поскольку, если какой-либо формат вывода команды немного отличается между ОС
версий/разновидностей, код парсинга также должен быть адаптирован, не говоря уже о различиях между локалями.
Получение списка файлов в папку с помощью bat файла
Один из самых доступных и доступных файлов в локальной сети. Существует несколько вариантов создания файла с расширением «.bat», с разным кодом.
Для создания bat файла вам необходимо будет открыть Блокнот, а затем вставить туда этот код:
chcp 1251 эхо %date% %time% >filelist.txt каталог /b /d >>filelist.txt
Сохраните этот файл, имя файла может дать любое, самому файлу нужно дать расширение «BAT». Параметры сохранения файла в Блокноте будут выглядеть примерно так:
- Имя файла: filelist.bat
- Тип файла: Все файлы
После этого нажмите кнопку «Сохранить».
Далее помещает созданный файл в ту папку, из которой вы хотите получить, список находящихся там файлов. После этого запустите файл с расширением «.bat». В данной папке будет создан файл «filelist» в формате «.txt», в котором будет находиться список файлов.
Существует несколько вариантов файла с расширением «.bat». При сборе этого метода проблем с кодировкой не возникло.
Сохранение списков файлов с помощью командной строки

После этого появится окно консоли, в котором уже будет указан путь к нужной директории (в следующем случае будет к той папке, которую вы видите). В этом открытии находится папка «Программы» на рабочем столе моего компьютера. В этой папке находятся другие папки, в которых находятся ярлыки программ.

Далее нужно будет ввести одну из этой команды:
каталог /b>filelist.txt каталог /s>filelist.txt
После ввода «dir» должен быть пробел. Вместо «filelist» можно написать свое название файла только латинскими буквами. Не следует включать в конце добавить формат «.txt».
Эти имена перечислены в списке расширенного списка файлов:
- /b — обозначает, что будут сохранены только имена файлов.
- /s — обозначает, что дополнительно в список будут включены все файлы и подкаталоги (подпапки), которые находятся в этой папке.

Затем на клавиатуре нажмите на кнопку «Enter».
После этого вы можете открыть папку и увидеть, что в папке находится текстовый файл «filelist». Теперь можете открыть этот файл с помощью Блокнота.
Если в данной папке некоторые файлы имели русские имена, то вместо имен этих файлов, вы увидите непонятные символы (крякозябры). Дело в том, что программа Блокнот не понимает кодировку MS-DOS.
Поэтому, открыть созданный файл, можно будет с помощью программы Word. Предполагаю, что у большинства пользователей, на компьютере установлена данная программа.
Кликните по текстовому файлу правой кнопкой мыши, а затем в контекстном меню выберите пункт «Открыть с помощью». Выберите для открытия файла программу Microsoft Office Word. В окне программы Word будет открыто окно «Преобразование текста», в котором нужно будет выбрать кодировку MS-DOS, которая позволит прочитать этот документ.
На образце вы увидите правильное отображение текста.

После нажатия на кнопку «ОК», данный текст будет открыт в программе Word. Вы можете провести редактирование документа, а потом сохранить его на компьютере в нужном формате, в том числе в формате «TXT». Проблем с кодировкой после сохранения файла уже не будет.
Сохранение списка файлов в папке в браузере
Получить список файлов в папке можно при помощи браузера. Сначала откройте браузер, а затем перетащите папку в окно браузера. Список файлов будет открыт в окне браузера. Между содержимым можно будет перемещаться как в Проводнике.
Далее можете просто скопировать список файлов в текстовый редактор, сохранить список в HTML файл, или сохранить в PDF при помощи виртуального принтера
.

List different types of files using find and ls
- For
find
, see this answer
. See also my comment here
. - For
ls
, see linuxhandbook.com: How to List Only Directories in Linux
Tip:
for any of the find
examples below, you can pipe the output to sort -V
if you’d like it sorted.
find . -maxdepth 1 -type f | sort -V List only regular files
( -type f
) 1 level deep:
# General form
find "path/to/some/dir" -maxdepth 1 -type f
# In current directory
find . -maxdepth 1 -type f List only symbolic links
( -type l
) 1 level deep:
# General form
find "path/to/some/dir" -maxdepth 1 -type l
# In current directory
find . -maxdepth 1 -type l List only directories
( -type d
) 1 level deep:
Note that for the find
example here, we also add -mindepth 1
in order to exclude the current directory, .
, which would be printed as .
at the top of the directory list otherwise. See here: How to exclude this / current / dot folder from find “type d”
# General form
find "path/to/some/dir" -mindepth 1 -maxdepth 1 -type d
# In current directory
find . -mindepth 1 -maxdepth 1 -type d
# OR, using `ls`:
ls -d Combine some of the above: list only regular files
and symbolic links
( -type f,l
) 1 level deep:
Use a comma ( ,
) to separate arguments to -type
:
# General form
find "path/to/some/dir" -maxdepth 1 -type f,l
# In current directory
find . -maxdepth 1 -type f,l Получаем список файлов в Total Commander
Получить список файлов в папке можно при помощи популярного файлового менеджера Total Commander. Для этого, открываете в окне программы нужную папку.
В меню «Выделение», сначала выбираете пункт «Выделить всё». После того, как все файлы были выделены, в этом же меню выбираете пункт «Копировать имена в буфер».

Потом открываете Блокнот или другой текстовый редактор, и вставляете туда список файлов из буфера обмена.
Выводы статьи
При помощи таких достаточно простых способов, вы можете легко создать список файлов, которые находятся в конкретной папке или на диске вашего компьютера. Вы можете использовать наиболее удобный для себя способ сохранения списка файлов.
3 способа получить список файлов в папке (видео)



