Создайте отдельный текстовый файл для отображения содержимого в каждом каталоге и подкаталоге

Если вы доверяете get.docker.com, запустите:

curl -sSL https://get.docker.com/ | sudo bash
4
задан 2 April 2017 в 11:12

15 ответов

Сценарий ниже добавит список ко всем субдирерам из каталога рекурсивно:

#!/usr/bin/env python3
import os
import sys

for root, dirs, files in os.walk(sys.argv[1]):
    for dr in dirs:
        dr = os.path.join(root, dr)
        open(os.path.join(dr, "list.txt"), "wt").write(
            ",".join(f for f in os.listdir(dr) if f != "list.txt")
            )

Использовать

Скопировать сценарий в пустой файл, сохранить его как dirlists.py Запустите его с основным каталогом в качестве аргумента:
python3 /path/to/dirlists.py /path/to/maindirectory

Примечание

Как уже упоминалось, скрипт добавляет list.txt ко всем sub - [!d1 ]. Если вы также хотите или хотите иметь список в главном (корневом) -dir вашего каталога, укажите:

Объяснение

Скопируйте сценарий в пустой файл , сохраните его как dirlists.py Создайте список содержимого для каждого из них:
os.listdir(dr)
Запустите его с основным каталогом в качестве аргумента:
python3 /path/to/dirlists.py /path/to/maindirectory

EDIT

Как запрошено в комментарии:

Если вам нужна строка в list.txt, чтобы закончить запятую, просто замените: [!d23 ]

",".join(f for f in os.listdir(dr) if f != "list.txt")

by:

",".join(f for f in os.listdir(dr) if f != "list.txt")+","

Учесть отступ, поместить замену в том же положении

5
ответ дан 23 May 2018 в 00:03

Сценарий ниже добавит список ко всем субдирерам из каталога рекурсивно:

#!/usr/bin/env python3 import os import sys for root, dirs, files in os.walk(sys.argv[1]): for dr in dirs: dr = os.path.join(root, dr) open(os.path.join(dr, "list.txt"), "wt").write( ",".join(f for f in os.listdir(dr) if f != "list.txt") )

Использовать

Скопировать сценарий в пустой файл, сохранить его как dirlists.py Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

Примечание

Как уже упоминалось, скрипт добавляет list.txt ко всем sub - . Если вы также хотите или хотите иметь список в главном (корневом) -dir вашего каталога, укажите:

Объяснение

Скопируйте сценарий в пустой файл , сохраните его как dirlists.py Создайте список содержимого для каждого из них: os.listdir(dr) Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

EDIT

Как запрошено в комментарии:

Если вам нужна строка в list.txt, чтобы закончить запятую, просто замените:

",".join(f for f in os.listdir(dr) if f != "list.txt")

by:

",".join(f for f in os.listdir(dr) if f != "list.txt")+","

Учесть отступ, поместить замену в том же положении

5
ответ дан 18 July 2018 в 15:40

Сценарий ниже добавит список ко всем субдирерам из каталога рекурсивно:

#!/usr/bin/env python3 import os import sys for root, dirs, files in os.walk(sys.argv[1]): for dr in dirs: dr = os.path.join(root, dr) open(os.path.join(dr, "list.txt"), "wt").write( ",".join(f for f in os.listdir(dr) if f != "list.txt") )

Использовать

Скопировать сценарий в пустой файл, сохранить его как dirlists.py Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

Примечание

Как уже упоминалось, скрипт добавляет list.txt ко всем sub - . Если вы также хотите или хотите иметь список в главном (корневом) -dir вашего каталога, укажите:

Объяснение

Скопируйте сценарий в пустой файл , сохраните его как dirlists.py Создайте список содержимого для каждого из них: os.listdir(dr) Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

EDIT

Как запрошено в комментарии:

Если вам нужна строка в list.txt, чтобы закончить запятую, просто замените:

",".join(f for f in os.listdir(dr) if f != "list.txt")

by:

",".join(f for f in os.listdir(dr) if f != "list.txt")+","

Учесть отступ, поместить замену в том же положении

5
ответ дан 24 July 2018 в 20:41

Сценарий ниже добавит список ко всем субдирерам из каталога рекурсивно:

#!/usr/bin/env python3 import os import sys for root, dirs, files in os.walk(sys.argv[1]): for dr in dirs: dr = os.path.join(root, dr) open(os.path.join(dr, "list.txt"), "wt").write( ",".join(f for f in os.listdir(dr) if f != "list.txt") )

Использовать

Скопировать сценарий в пустой файл, сохранить его как dirlists.py Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

Примечание

Как уже упоминалось, скрипт добавляет list.txt ко всем sub - . Если вы также хотите или хотите иметь список в главном (корневом) -dir вашего каталога, укажите:

Объяснение

Скопируйте сценарий в пустой файл , сохраните его как dirlists.py Создайте список содержимого для каждого из них: os.listdir(dr) Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

EDIT

Как запрошено в комментарии:

Если вам нужна строка в list.txt, чтобы закончить запятую, просто замените:

",".join(f for f in os.listdir(dr) if f != "list.txt")

by:

",".join(f for f in os.listdir(dr) if f != "list.txt")+","

Учесть отступ, поместить замену в том же положении

5
ответ дан 31 July 2018 в 12:43

Сценарий ниже добавит список ко всем субдирерам из каталога рекурсивно:

#!/usr/bin/env python3 import os import sys for root, dirs, files in os.walk(sys.argv[1]): for dr in dirs: dr = os.path.join(root, dr) open(os.path.join(dr, "list.txt"), "wt").write( ",".join(f for f in os.listdir(dr) if f != "list.txt") )

Использовать

Скопировать сценарий в пустой файл, сохранить его как dirlists.py Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

Примечание

Как уже упоминалось, скрипт добавляет list.txt ко всем sub - . Если вы также хотите или хотите иметь список в главном (корневом) -dir вашего каталога, укажите:

Объяснение

Скопируйте сценарий в пустой файл , сохраните его как dirlists.py Создайте список содержимого для каждого из них: os.listdir(dr) Запустите его с основным каталогом в качестве аргумента: python3 /path/to/dirlists.py /path/to/maindirectory

EDIT

Как запрошено в комментарии:

Если вам нужна строка в list.txt, чтобы закончить запятую, просто замените:

",".join(f for f in os.listdir(dr) if f != "list.txt")

by:

",".join(f for f in os.listdir(dr) if f != "list.txt")+","

Учесть отступ, поместить замену в том же положении

5
ответ дан 31 July 2018 в 23:43

Чтобы сделать его рекурсивным, сначала включите globstar

shopt -s globstar

Затем в родительском каталоге (A в вашей структуре) вы можете запустить:

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') |tee "$d"/list.txt ; done

или немного более читаемо

for d in **; do 
  [[ -d "$d" ]] && 
  (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') | tee "$d"/list.txt
done

, который, если каталог a содержит

├── a
│   ├── 1.txt
│   ├── 2.txt
│   ├── 3.txt
│   ├── a badly named file &
│   └── Z

, создаст список в каталоге a, который выглядит так: [ ! d4]

2.txt,1.txt,3.txt,Z,a badly named file &

find не производит упорядоченный вывод, поэтому, если это проблема, мне придется подумать о лучшем способе. [F12] в выражении find состоит в том, чтобы исключить включение самого списка, а выражение sed - только для удаления конечной запятой. Поражайте все эти дополнительные байты.

Когда вы закончите

shopt -u globstar
, вы можете отключить globstar
4
ответ дан 23 May 2018 в 00:03
  • 1
    Спасибо за код. Он отлично справился с уровнем1, но предположим, что если у меня есть файл в папке «Z», в него должен быть внесен «list.txt» с листингом файла в нем .. любое обходное решение для этого? – Derek James 2 April 2017 в 10:09
  • 2
    @DerekJames уверен - легко исправлено - см. Мое редактирование :) – Zanna 2 April 2017 в 10:34
  • 3
    проверил код ... Его добавление названия файлов, которые находятся во внутреннем каталоге тоже .. – Derek James 2 April 2017 в 11:41
  • 4
    @DerekJames, о да, исправлено это сейчас ... но похоже, глупое количество указаний глубины ... должно быть лучше ... – Zanna 2 April 2017 в 11:46
  • 5
    хе-хе .. спасибо кстати за помощь .. – Derek James 2 April 2017 в 12:01

Версия с одним слоем

Используйте find, чтобы сначала получить каталоги, затем оболочка выполнит для вас работу:

$ tree                                                                                                                                                
.
├── a_directory
│   ├── a_file
│   ├── a_subdir
│   └── mv-files.py
└── another_dir
    ├── {file}1
    └── {file}2

3 directories, 4 files

$  find -type d -exec bash -c 'cd $1; find  -maxdepth 1  -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}"  > list.txt' bash "{}" \;

$ cat a_directory/list.txt                                                                                                                            
mv-files.py,a_file,list.txt,a_subdir

Как это работает:

мы используем команду find с -type d, чтобы отфильтровать все инструкции каталогов -exec с помощью \; terminator, чтобы мы могли запускать указанную команду для каждого аргумента, который find получает в -exec, который мы запускаем bash с флагом -c, с которым мы передаем аргумент $0 аргумента bash и $1, являющийся каталогом, который outter find locaed bash будет вводить данный каталог и использовать find с аргументом - maxdepth 1 чтобы ограничить эту команду только этим подкаталогом. -not -name "." исключает ссылку каталога ., которая ссылается на self. Затем мы передаем текст в awk, который служит только для удаления последнего ,, указанного find, так что у нас есть действительный список CSV. Обратите внимание на использование двойных кавычек и \$. Это предназначено для упрощения цитирования и предотвращения интерпретации bash $0 как своих собственных позиционных аргументов, а скорее как команды awk. Весь список элементов, которые получает внутренний find, будет отправлен на list.txt через перенаправление >.

Дополнительным усовершенствованием этого может быть использование -not -name "list.txt" внутри внутренней команды find для исключения самого файла списка (потому что из-за >, всегда создающего файл для записи первым, list.txt также будет появятся в списке).

Лично, если бы я делал это для себя, я бы написал список файлов с разделителем \0, чтобы избежать трудностей с именами файлов, но это также требует запоминания того, что [ f36] находится в формате \0 и записывает для него функцию парсера.

Полная версия скрипта

Для удобства чтения здесь представлена ​​полная версия скрипта вместо однострочного.

Сценарий:

#!/bin/bash
# note : this assumes you run the script from top-most directory
find  -type d  | while IFS= read -r directory;
do
    cd "$directory"
    find  -maxdepth 1  -not -name "." -not -name "list.txt" -printf "%f," |
    awk "{print substr(\$0,0,length(\$0)-1)}"  > list.txt
    cd - > /dev/null
done

Обратите внимание, что этот скрипт запускается из самого верхнего каталога. Он также включает «я» в список, если он хранится в том же каталоге. Если вы поместите его на ~/bin, например (или любой другой каталог, принадлежащий переменной $PATH), и запустите его, имя сценария не появится в списке.

Тест:

$ tree                                                                                                                                                
.
├── a_directory
│   ├── a_file
│   ├── a_subdir
│   └── mv-files.py
├── another_dir
│   ├── {file}1
│   └── {file}2
└── make_lists.sh

3 directories, 5 files

$ ./make_lists.sh                                                                                                                                     

$ tree
.
├── a_directory
│   ├── a_file
│   ├── a_subdir
│   │   └── list.txt
│   ├── list.txt
│   └── mv-files.py
├── another_dir
│   ├── {file}1
│   ├── {file}2
│   └── list.txt
├── list.txt
└── make_lists.sh

3 directories, 9 files

$ cat a_directory/list.txt                                                                                                                            
mv-files.py,a_file,a_subdir
3
ответ дан 23 May 2018 в 00:03
  • 1
    Спасибо за такой отличный ответ. Он работает для меня, но требует небольшого изменения производительности. Если «list.txt» может выводить файлы с запятой, как я уже упоминал в примере, это было бы прекрасно – Derek James 2 April 2017 в 10:30
  • 2
    @DerekJames Я только что сделал редактирование, чтобы включить это, хотя он сделал команду немного дольше, чтобы сделать ее действительным CSV-файлом. Честно говоря, я бы написал его несколько иначе, как полный сценарий оболочки. Дайте мне знать, если вы хотите, чтобы это было включено. Вероятно, это будет более читаемым – Sergiy Kolodyazhnyy 2 April 2017 в 10:36
  • 3
    Пример вывода @DerekJames все еще старый. Позвольте мне изменить это в секунду – Sergiy Kolodyazhnyy 2 April 2017 в 10:38
  • 4
    @DerekJames любые другие вопросы? как он работает на вас? – Sergiy Kolodyazhnyy 2 April 2017 в 10:48
  • 5
    получение 'list.txt' в создаваемом файле .. и как u used -name на этот раз, как добавить -not -name"list.txt", как сказано вами. – Derek James 2 April 2017 в 11:03

Версия с одним слоем

Используйте find, чтобы сначала получить каталоги, затем оболочка выполнит для вас работу:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py └── another_dir ├── {file}1 └── {file}2 3 directories, 4 files $ find -type d -exec bash -c 'cd $1; find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt' bash "{}" \; $ cat a_directory/list.txt mv-files.py,a_file,list.txt,a_subdir

Как это работает:

мы используем команду find с -type d, чтобы отфильтровать все инструкции каталогов -exec с помощью \; terminator, чтобы мы могли запускать указанную команду для каждого аргумента, который find получает в -exec, который мы запускаем bash с флагом -c, с которым мы передаем аргумент $0 аргумента bash и $1, являющийся каталогом, который outter find locaed bash будет вводить данный каталог и использовать find с аргументом - maxdepth 1 чтобы ограничить эту команду только этим подкаталогом. -not -name "." исключает ссылку каталога ., которая ссылается на self. Затем мы передаем текст в awk, который служит только для удаления последнего ,, указанного find, так что у нас есть действительный список CSV. Обратите внимание на использование двойных кавычек и \$. Это предназначено для упрощения цитирования и предотвращения интерпретации bash $0 как своих собственных позиционных аргументов, а скорее как команды awk. Весь список элементов, которые получает внутренний find, будет отправлен на list.txt через перенаправление >.

Дополнительным усовершенствованием этого может быть использование -not -name "list.txt" внутри внутренней команды find для исключения самого файла списка (потому что из-за >, всегда создающего файл для записи первым, list.txt также будет появятся в списке).

Лично, если бы я делал это для себя, я бы написал список файлов с разделителем \0, чтобы избежать трудностей с именами файлов, но это также требует запоминания того, что list.txt находится в формате \0 и записывает для него функцию парсера.

Полная версия скрипта

Для удобства чтения здесь представлена ​​полная версия скрипта вместо однострочного.

Сценарий:

#!/bin/bash # note : this assumes you run the script from top-most directory find -type d | while IFS= read -r directory; do cd "$directory" find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt cd - > /dev/null done

Обратите внимание, что этот скрипт запускается из самого верхнего каталога. Он также включает «я» в список, если он хранится в том же каталоге. Если вы поместите его на ~/bin, например (или любой другой каталог, принадлежащий переменной $PATH), и запустите его, имя сценария не появится в списке.

Тест:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py ├── another_dir │   ├── {file}1 │   └── {file}2 └── make_lists.sh 3 directories, 5 files $ ./make_lists.sh $ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   │   └── list.txt │   ├── list.txt │   └── mv-files.py ├── another_dir │   ├── {file}1 │   ├── {file}2 │   └── list.txt ├── list.txt └── make_lists.sh 3 directories, 9 files $ cat a_directory/list.txt mv-files.py,a_file,a_subdir
3
ответ дан 18 July 2018 в 15:40

Чтобы сделать его рекурсивным, сначала включите globstar

shopt -s globstar

Затем в родительском каталоге (A в вашей структуре) вы можете запустить:

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') |tee "$d"/list.txt ; done

или немного более читаемо

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') | tee "$d"/list.txt done

, который, если каталог a содержит

├── a │   ├── 1.txt │   ├── 2.txt │   ├── 3.txt │   ├── a badly named file & │   └── Z

, создаст список в каталоге a, который выглядит так: [ ! d4] 2.txt,1.txt,3.txt,Z,a badly named file &

find не производит упорядоченный вывод, поэтому, если это проблема, мне придется подумать о лучшем способе. [F12] в выражении find состоит в том, чтобы исключить включение самого списка, а выражение sed - только для удаления конечной запятой. Поражайте все эти дополнительные байты.

Когда вы закончите

shopt -u globstar , вы можете отключить globstar
4
ответ дан 18 July 2018 в 15:40

Версия с одним слоем

Используйте find, чтобы сначала получить каталоги, затем оболочка выполнит для вас работу:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py └── another_dir ├── {file}1 └── {file}2 3 directories, 4 files $ find -type d -exec bash -c 'cd $1; find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt' bash "{}" \; $ cat a_directory/list.txt mv-files.py,a_file,list.txt,a_subdir

Как это работает:

мы используем команду find с -type d, чтобы отфильтровать все инструкции каталогов -exec с помощью \; terminator, чтобы мы могли запускать указанную команду для каждого аргумента, который find получает в -exec, который мы запускаем bash с флагом -c, с которым мы передаем аргумент $0 аргумента bash и $1, являющийся каталогом, который outter find locaed bash будет вводить данный каталог и использовать find с аргументом - maxdepth 1 чтобы ограничить эту команду только этим подкаталогом. -not -name "." исключает ссылку каталога ., которая ссылается на self. Затем мы передаем текст в awk, который служит только для удаления последнего ,, указанного find, так что у нас есть действительный список CSV. Обратите внимание на использование двойных кавычек и \$. Это предназначено для упрощения цитирования и предотвращения интерпретации bash $0 как своих собственных позиционных аргументов, а скорее как команды awk. Весь список элементов, которые получает внутренний find, будет отправлен на list.txt через перенаправление >.

Дополнительным усовершенствованием этого может быть использование -not -name "list.txt" внутри внутренней команды find для исключения самого файла списка (потому что из-за >, всегда создающего файл для записи первым, list.txt также будет появятся в списке).

Лично, если бы я делал это для себя, я бы написал список файлов с разделителем \0, чтобы избежать трудностей с именами файлов, но это также требует запоминания того, что list.txt находится в формате \0 и записывает для него функцию парсера.

Полная версия скрипта

Для удобства чтения здесь представлена ​​полная версия скрипта вместо однострочного.

Сценарий:

#!/bin/bash # note : this assumes you run the script from top-most directory find -type d | while IFS= read -r directory; do cd "$directory" find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt cd - > /dev/null done

Обратите внимание, что этот скрипт запускается из самого верхнего каталога. Он также включает «я» в список, если он хранится в том же каталоге. Если вы поместите его на ~/bin, например (или любой другой каталог, принадлежащий переменной $PATH), и запустите его, имя сценария не появится в списке.

Тест:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py ├── another_dir │   ├── {file}1 │   └── {file}2 └── make_lists.sh 3 directories, 5 files $ ./make_lists.sh $ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   │   └── list.txt │   ├── list.txt │   └── mv-files.py ├── another_dir │   ├── {file}1 │   ├── {file}2 │   └── list.txt ├── list.txt └── make_lists.sh 3 directories, 9 files $ cat a_directory/list.txt mv-files.py,a_file,a_subdir
3
ответ дан 24 July 2018 в 20:41
  • 1
    Спасибо за такой отличный ответ. Он работает для меня, но требует небольшого изменения производительности. Если «list.txt» может выводить файлы с запятой, как я уже упоминал в примере, это было бы прекрасно – Derek James 2 April 2017 в 10:30
  • 2
    @DerekJames Я только что сделал редактирование, чтобы включить это, хотя он сделал команду немного дольше, чтобы сделать ее действительным CSV-файлом. Честно говоря, я бы написал его несколько иначе, как полный сценарий оболочки. Дайте мне знать, если вы хотите, чтобы это было включено. Вероятно, это будет более читаемым – Sergiy Kolodyazhnyy 2 April 2017 в 10:36
  • 3
    Пример вывода @DerekJames все еще старый. Позвольте мне изменить это в секунду – Sergiy Kolodyazhnyy 2 April 2017 в 10:38
  • 4
    @DerekJames любые другие вопросы? как он работает на вас? – Sergiy Kolodyazhnyy 2 April 2017 в 10:48
  • 5
    получение 'list.txt' в создаваемом файле .. и как u used -name на этот раз, как добавить -not -name"list.txt", как сказано вами. – Derek James 2 April 2017 в 11:03

Чтобы сделать его рекурсивным, сначала включите globstar

shopt -s globstar

Затем в родительском каталоге (A в вашей структуре) вы можете запустить:

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') |tee "$d"/list.txt ; done

или немного более читаемо

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') | tee "$d"/list.txt done

, который, если каталог a содержит

├── a │   ├── 1.txt │   ├── 2.txt │   ├── 3.txt │   ├── a badly named file & │   └── Z

, создаст список в каталоге a, который выглядит так: [ ! d4] 2.txt,1.txt,3.txt,Z,a badly named file &

find не производит упорядоченный вывод, поэтому, если это проблема, мне придется подумать о лучшем способе. [F12] в выражении find состоит в том, чтобы исключить включение самого списка, а выражение sed - только для удаления конечной запятой. Поражайте все эти дополнительные байты.

Когда вы закончите

shopt -u globstar , вы можете отключить globstar
4
ответ дан 24 July 2018 в 20:41
  • 1
    Спасибо за код. Он отлично справился с уровнем1, но предположим, что если у меня есть файл в папке «Z», в него должен быть внесен «list.txt» с листингом файла в нем .. любое обходное решение для этого? – Derek James 2 April 2017 в 10:09
  • 2
    @DerekJames уверен - легко исправлено - см. Мое редактирование :) – Zanna 2 April 2017 в 10:34
  • 3
    проверил код ... Его добавление названия файлов, которые находятся во внутреннем каталоге тоже .. – Derek James 2 April 2017 в 11:41
  • 4
    @DerekJames, о да, исправлено это сейчас ... но похоже, глупое количество указаний глубины ... должно быть лучше ... – Zanna 2 April 2017 в 11:46
  • 5
    хе-хе .. спасибо кстати за помощь .. – Derek James 2 April 2017 в 12:01

Версия с одним слоем

Используйте find, чтобы сначала получить каталоги, затем оболочка выполнит для вас работу:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py └── another_dir ├── {file}1 └── {file}2 3 directories, 4 files $ find -type d -exec bash -c 'cd $1; find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt' bash "{}" \; $ cat a_directory/list.txt mv-files.py,a_file,list.txt,a_subdir

Как это работает:

мы используем команду find с -type d, чтобы отфильтровать все инструкции каталогов -exec с помощью \; terminator, чтобы мы могли запускать указанную команду для каждого аргумента, который find получает в -exec, который мы запускаем bash с флагом -c, с которым мы передаем аргумент $0 аргумента bash и $1, являющийся каталогом, который outter find locaed bash будет вводить данный каталог и использовать find с аргументом - maxdepth 1 чтобы ограничить эту команду только этим подкаталогом. -not -name "." исключает ссылку каталога ., которая ссылается на self. Затем мы передаем текст в awk, который служит только для удаления последнего ,, указанного find, так что у нас есть действительный список CSV. Обратите внимание на использование двойных кавычек и \$. Это предназначено для упрощения цитирования и предотвращения интерпретации bash $0 как своих собственных позиционных аргументов, а скорее как команды awk. Весь список элементов, которые получает внутренний find, будет отправлен на list.txt через перенаправление >.

Дополнительным усовершенствованием этого может быть использование -not -name "list.txt" внутри внутренней команды find для исключения самого файла списка (потому что из-за >, всегда создающего файл для записи первым, list.txt также будет появятся в списке).

Лично, если бы я делал это для себя, я бы написал список файлов с разделителем \0, чтобы избежать трудностей с именами файлов, но это также требует запоминания того, что list.txt находится в формате \0 и записывает для него функцию парсера.

Полная версия скрипта

Для удобства чтения здесь представлена ​​полная версия скрипта вместо однострочного.

Сценарий:

#!/bin/bash # note : this assumes you run the script from top-most directory find -type d | while IFS= read -r directory; do cd "$directory" find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt cd - > /dev/null done

Обратите внимание, что этот скрипт запускается из самого верхнего каталога. Он также включает «я» в список, если он хранится в том же каталоге. Если вы поместите его на ~/bin, например (или любой другой каталог, принадлежащий переменной $PATH), и запустите его, имя сценария не появится в списке.

Тест:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py ├── another_dir │   ├── {file}1 │   └── {file}2 └── make_lists.sh 3 directories, 5 files $ ./make_lists.sh $ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   │   └── list.txt │   ├── list.txt │   └── mv-files.py ├── another_dir │   ├── {file}1 │   ├── {file}2 │   └── list.txt ├── list.txt └── make_lists.sh 3 directories, 9 files $ cat a_directory/list.txt mv-files.py,a_file,a_subdir
3
ответ дан 31 July 2018 в 12:43
  • 1
    Спасибо за такой отличный ответ. Он работает для меня, но требует небольшого изменения производительности. Если «list.txt» может выводить файлы с запятой, как я уже упоминал в примере, это было бы прекрасно – Derek James 2 April 2017 в 10:30
  • 2
    @DerekJames Я только что сделал редактирование, чтобы включить это, хотя он сделал команду немного дольше, чтобы сделать ее действительным CSV-файлом. Честно говоря, я бы написал его несколько иначе, как полный сценарий оболочки. Дайте мне знать, если вы хотите, чтобы это было включено. Вероятно, это будет более читаемым – Sergiy Kolodyazhnyy 2 April 2017 в 10:36
  • 3
    Пример вывода @DerekJames все еще старый. Позвольте мне изменить это в секунду – Sergiy Kolodyazhnyy 2 April 2017 в 10:38
  • 4
    @DerekJames любые другие вопросы? как он работает на вас? – Sergiy Kolodyazhnyy 2 April 2017 в 10:48
  • 5
    получение 'list.txt' в создаваемом файле .. и как u used -name на этот раз, как добавить -not -name"list.txt", как сказано вами. – Derek James 2 April 2017 в 11:03

Чтобы сделать его рекурсивным, сначала включите globstar

shopt -s globstar

Затем в родительском каталоге (A в вашей структуре) вы можете запустить:

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') |tee "$d"/list.txt ; done

или немного более читаемо

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') | tee "$d"/list.txt done

, который, если каталог a содержит

├── a │   ├── 1.txt │   ├── 2.txt │   ├── 3.txt │   ├── a badly named file & │   └── Z

, создаст список в каталоге a, который выглядит так: [ ! d4] 2.txt,1.txt,3.txt,Z,a badly named file &

find не производит упорядоченный вывод, поэтому, если это проблема, мне придется подумать о лучшем способе. [F12] в выражении find состоит в том, чтобы исключить включение самого списка, а выражение sed - только для удаления конечной запятой. Поражайте все эти дополнительные байты.

Когда вы закончите

shopt -u globstar , вы можете отключить globstar
4
ответ дан 31 July 2018 в 12:43
  • 1
    Спасибо за код. Он отлично справился с уровнем1, но предположим, что если у меня есть файл в папке «Z», в него должен быть внесен «list.txt» с листингом файла в нем .. любое обходное решение для этого? – Derek James 2 April 2017 в 10:09
  • 2
    @DerekJames уверен - легко исправлено - см. Мое редактирование :) – Zanna 2 April 2017 в 10:34
  • 3
    проверил код ... Его добавление названия файлов, которые находятся во внутреннем каталоге тоже .. – Derek James 2 April 2017 в 11:41
  • 4
    @DerekJames, о да, исправлено это сейчас ... но похоже, глупое количество указаний глубины ... должно быть лучше ... – Zanna 2 April 2017 в 11:46
  • 5
    хе-хе .. спасибо кстати за помощь .. – Derek James 2 April 2017 в 12:01

Версия с одним слоем

Используйте find, чтобы сначала получить каталоги, затем оболочка выполнит для вас работу:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py └── another_dir ├── {file}1 └── {file}2 3 directories, 4 files $ find -type d -exec bash -c 'cd $1; find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt' bash "{}" \; $ cat a_directory/list.txt mv-files.py,a_file,list.txt,a_subdir

Как это работает:

мы используем команду find с -type d, чтобы отфильтровать все инструкции каталогов -exec с помощью \; terminator, чтобы мы могли запускать указанную команду для каждого аргумента, который find получает в -exec, который мы запускаем bash с флагом -c, с которым мы передаем аргумент $0 аргумента bash и $1, являющийся каталогом, который outter find locaed bash будет вводить данный каталог и использовать find с аргументом - maxdepth 1 чтобы ограничить эту команду только этим подкаталогом. -not -name "." исключает ссылку каталога ., которая ссылается на self. Затем мы передаем текст в awk, который служит только для удаления последнего ,, указанного find, так что у нас есть действительный список CSV. Обратите внимание на использование двойных кавычек и \$. Это предназначено для упрощения цитирования и предотвращения интерпретации bash $0 как своих собственных позиционных аргументов, а скорее как команды awk. Весь список элементов, которые получает внутренний find, будет отправлен на list.txt через перенаправление >.

Дополнительным усовершенствованием этого может быть использование -not -name "list.txt" внутри внутренней команды find для исключения самого файла списка (потому что из-за >, всегда создающего файл для записи первым, list.txt также будет появятся в списке).

Лично, если бы я делал это для себя, я бы написал список файлов с разделителем \0, чтобы избежать трудностей с именами файлов, но это также требует запоминания того, что list.txt находится в формате \0 и записывает для него функцию парсера.

Полная версия скрипта

Для удобства чтения здесь представлена ​​полная версия скрипта вместо однострочного.

Сценарий:

#!/bin/bash # note : this assumes you run the script from top-most directory find -type d | while IFS= read -r directory; do cd "$directory" find -maxdepth 1 -not -name "." -not -name "list.txt" -printf "%f," | awk "{print substr(\$0,0,length(\$0)-1)}" > list.txt cd - > /dev/null done

Обратите внимание, что этот скрипт запускается из самого верхнего каталога. Он также включает «я» в список, если он хранится в том же каталоге. Если вы поместите его на ~/bin, например (или любой другой каталог, принадлежащий переменной $PATH), и запустите его, имя сценария не появится в списке.

Тест:

$ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   └── mv-files.py ├── another_dir │   ├── {file}1 │   └── {file}2 └── make_lists.sh 3 directories, 5 files $ ./make_lists.sh $ tree . ├── a_directory │   ├── a_file │   ├── a_subdir │   │   └── list.txt │   ├── list.txt │   └── mv-files.py ├── another_dir │   ├── {file}1 │   ├── {file}2 │   └── list.txt ├── list.txt └── make_lists.sh 3 directories, 9 files $ cat a_directory/list.txt mv-files.py,a_file,a_subdir
3
ответ дан 31 July 2018 в 23:43
  • 1
    Спасибо за такой отличный ответ. Он работает для меня, но требует небольшого изменения производительности. Если «list.txt» может выводить файлы с запятой, как я уже упоминал в примере, это было бы прекрасно – Derek James 2 April 2017 в 10:30
  • 2
    @DerekJames Я только что сделал редактирование, чтобы включить это, хотя он сделал команду немного дольше, чтобы сделать ее действительным CSV-файлом. Честно говоря, я бы написал его несколько иначе, как полный сценарий оболочки. Дайте мне знать, если вы хотите, чтобы это было включено. Вероятно, это будет более читаемым – Sergiy Kolodyazhnyy 2 April 2017 в 10:36
  • 3
    Пример вывода @DerekJames все еще старый. Позвольте мне изменить это в секунду – Sergiy Kolodyazhnyy 2 April 2017 в 10:38
  • 4
    @DerekJames любые другие вопросы? как он работает на вас? – Sergiy Kolodyazhnyy 2 April 2017 в 10:48
  • 5
    получение 'list.txt' в создаваемом файле .. и как u used -name на этот раз, как добавить -not -name"list.txt", как сказано вами. – Derek James 2 April 2017 в 11:03

Чтобы сделать его рекурсивным, сначала включите globstar

shopt -s globstar

Затем в родительском каталоге (A в вашей структуре) вы можете запустить:

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') |tee "$d"/list.txt ; done

или немного более читаемо

for d in **; do [[ -d "$d" ]] && (find "$d" -mindepth 1 -maxdepth 1 \( -not -name "list.txt" \) -printf '%f,' | sed 's/,$/\n/') | tee "$d"/list.txt done

, который, если каталог a содержит

├── a │   ├── 1.txt │   ├── 2.txt │   ├── 3.txt │   ├── a badly named file & │   └── Z

, создаст список в каталоге a, который выглядит так: [ ! d4] 2.txt,1.txt,3.txt,Z,a badly named file &

find не производит упорядоченный вывод, поэтому, если это проблема, мне придется подумать о лучшем способе. [F12] в выражении find состоит в том, чтобы исключить включение самого списка, а выражение sed - только для удаления конечной запятой. Поражайте все эти дополнительные байты.

Когда вы закончите

shopt -u globstar , вы можете отключить globstar
4
ответ дан 31 July 2018 в 23:43
  • 1
    Спасибо за код. Он отлично справился с уровнем1, но предположим, что если у меня есть файл в папке «Z», в него должен быть внесен «list.txt» с листингом файла в нем .. любое обходное решение для этого? – Derek James 2 April 2017 в 10:09
  • 2
    @DerekJames уверен - легко исправлено - см. Мое редактирование :) – Zanna 2 April 2017 в 10:34
  • 3
    проверил код ... Его добавление названия файлов, которые находятся во внутреннем каталоге тоже .. – Derek James 2 April 2017 в 11:41
  • 4
    @DerekJames, о да, исправлено это сейчас ... но похоже, глупое количество указаний глубины ... должно быть лучше ... – Zanna 2 April 2017 в 11:46
  • 5
    хе-хе .. спасибо кстати за помощь .. – Derek James 2 April 2017 в 12:01

Другие вопросы по тегам:

Похожие вопросы: