- 8 ответов
- Вариант 1: ssh
- Вариант 2: переменные среды
- Вариант 3: файлы конфигурации
- Вариант 4: модуль python
- Вариант 3: файлы конфигурации
- Как делать не надо
- Ключи параметров ведения журнала
- Команда copy
- Команда dir
- Команда move
- Команда xcopy
- Обзор robocopy gui utility ver. 3.1
- Пример
- Текущая позиция в файлах python
- Функция read()
- Функция readline()
- Функция rename()
- Функция write()
- Метод close()
8 ответов
Лучший ответ
Я рекомендую стратегию, аналогичную ssh-agent. Если вы не можете использовать ssh-agent напрямую, вы можете реализовать что-то подобное, чтобы ваш пароль оставался только в оперативной памяти. В задании cron могли быть настроены учетные данные для получения действительного пароля от агента при каждом его запуске, однократного использования и немедленной отмены ссылки с помощью оператора del
.
Администратору по-прежнему необходимо вводить пароль для запуска ssh-agent во время загрузки или чего-либо еще, но это разумный компромисс, который позволяет избежать сохранения простого текста в любом месте на диске.
библиотека ключей Python интегрируется с CryptProtectData
API в Windows (вместе с соответствующими API на Mac и Linux), который шифрует данные с учетными данными пользователя.
Простое использование:
import keyring
# the service is just a namespace for your app
service_id = 'IM_YOUR_APP!'
keyring.set_password(service_id, 'dustin', 'my secret password')
password = keyring.get_password(service_id, 'dustin') # retrieve password
Использование, если вы хотите сохранить имя пользователя в связке ключей:
import keyring
MAGIC_USERNAME_KEY = 'im_the_magic_username_key'
# the service is just a namespace for your app
service_id = 'IM_YOUR_APP!'
username = 'dustin'
# save password
keyring.set_password(service_id, username, "password")
# optionally, abuse `set_password` to save username onto keyring
# we're just using some known magic string in the username field
keyring.set_password(service_id, MAGIC_USERNAME_KEY, username)
Позже, чтобы получить информацию о связке ключей
# again, abusing `get_password` to get the username.
# after all, the keyring is just a key-value store
username = keyring.get_password(service_id, MAGIC_USERNAME_KEY)
password = keyring.get_password(service_id, username)
Элементы шифруются с использованием учетных данных операционной системы пользователя, поэтому другие приложения, работающие в вашей учетной записи, смогут получить доступ к паролю.
Чтобы немного скрыть эту уязвимость, вы могли бы каким-то образом зашифровать / запутать пароль перед его сохранением в связке ключей. Конечно, любой, кто нацелился на ваш сценарий, мог бы просто посмотреть на источник и выяснить, как дешифровать / разблокировать пароль, но вы, по крайней мере, не допустите, чтобы какое-то приложение пылесосило все пароли в хранилище и получало ваши. ,
Существует несколько вариантов хранения паролей и других секретов, которые должна использовать программа Python, особенно программа, которая должна работать в фоновом режиме, где она не может просто попросить пользователя ввести пароль.
Проблемы, которых следует избегать:
- Проверка пароля в системе контроля версий, где его могут увидеть другие разработчики или даже публика.
- Другие пользователи на том же сервере читают пароль из файла конфигурации или исходного кода.
- Наличие пароля в исходном файле, где другие могут видеть его через плечо, пока вы редактируете его.
Вариант 1: ssh
Это не всегда вариант, но, вероятно, лучший. Ваш закрытый ключ никогда не передается по сети, SSH просто выполняет математические вычисления, чтобы доказать, что у вас есть правильный ключ.
Чтобы это работало, вам нужно следующее:
- База данных или все, к чему вы обращаетесь, должно быть доступно по SSH. Попробуйте найти «SSH» плюс любой сервис, к которому вы обращаетесь. Например, “ssh postgresql”. Если это не функция в вашей базе данных, перейдите к следующей опции.
- Создайте учетную запись для запуска службы, которая будет выполнять вызовы в базу данных, и создать ключ SSH.
- Либо добавьте открытый ключ к службе, которую вы собираетесь вызывать, либо создайте локальную учетную запись на этом сервере и установите открытый ключ там.
Вариант 2: переменные среды
Этот самый простой, так что это может быть хорошим началом. Это хорошо описано в приложении из двенадцати факторов. Основная идея заключается в том, что ваш исходный код просто извлекает пароль или другие секреты из переменных среды, а затем вы настраиваете эти переменные среды в каждой системе, в которой вы запускаете программу. Также может быть приятно, если вы используете значения по умолчанию, которые будут работать для большинства разработчиков. Вы должны сбалансировать это с тем, чтобы сделать ваше программное обеспечение «безопасным по умолчанию».
Вот пример, который извлекает сервер, имя пользователя и пароль из переменных среды.
import os
server = os.getenv('MY_APP_DB_SERVER', 'localhost')
user = os.getenv('MY_APP_DB_USER', 'myapp')
password = os.getenv('MY_APP_DB_PASSWORD', '')
db_connect(server, user, password)
Посмотрите, как установить переменные среды в вашей операционной системе, и подумайте о запуске службы под собственной учетной записью. Таким образом, у вас нет конфиденциальных данных в переменных среды, когда вы запускаете программы под своей учетной записью. Когда вы настраиваете эти переменные среды, будьте особенно внимательны, чтобы другие пользователи не могли их прочитать. Проверьте права доступа к файлу, например. Конечно, любой пользователь с правами root сможет их прочитать, но с этим ничего не поделаешь.
Вариант 3: файлы конфигурации
Это очень похоже на переменные среды, но вы читаете секреты из текстового файла. Я все еще нахожу переменные среды более гибкими для таких вещей, как инструменты развертывания и серверы непрерывной интеграции. Если вы решите использовать файл конфигурации, Python поддерживает несколько форматов в стандартной библиотеке, например JSON, INI, netrc и XML. Вы также можете найти внешние пакеты, такие как PyYAML и TOML. Лично я считаю JSON и YAML наиболее простым в использовании, а YAML позволяет комментировать.
Три вещи, которые следует учитывать при использовании файлов конфигурации:
- Где файл? Возможно расположение по умолчанию, например
~/.my_app
, и параметр командной строки для использования другого расположения. - Убедитесь, что другие пользователи не могут прочитать файл.
- Очевидно, не фиксируйте файл конфигурации в исходном коде. Возможно, вы захотите зафиксировать шаблон, который пользователи могут скопировать в свой домашний каталог.
Вариант 4: модуль python
Некоторые проекты просто помещают свои секреты прямо в модуль Python.
# settings.py
db_server = 'dbhost1'
db_user = 'my_app'
db_password = 'correcthorsebatterystaple'
Затем импортируйте этот модуль, чтобы получить значения.
# my_app.py
from settings import db_server, db_user, db_password
db_connect(db_server, db_user, db_password)
Одним из проектов, использующих эту технику, является Django. Очевидно, что вы не должны фиксировать settings.py
в системе контроля версий, хотя вы можете захотеть зафиксировать файл с именем settings_template.py
, который пользователи могут копировать и изменять.
Я вижу несколько проблем с этой техникой:
- Разработчики могут случайно передать файл в систему контроля версий. Добавление его в
.gitignore
снижает этот риск. - Часть вашего кода не находится под контролем исходного кода. Если вы дисциплинированы и ввели здесь только строки и цифры, это не будет проблемой. Если вы начнете писать здесь классы фильтров журналирования, остановитесь!
Если ваш проект уже использует эту технику, легко перейти к переменным среды. Просто переместите все значения параметров в переменные среды и измените модуль Python для чтения из этих переменных среды.
Посмотрев ответы на этот и другие вопросы, я собрал некоторый код, используя несколько предложенных методов для шифрования и скрытия секретных данных. Этот код специально предназначен для случаев, когда сценарий должен запускаться без вмешательства пользователя (если пользователь запускает его вручную, лучше всего, чтобы он вставил пароль и оставил его в памяти только в соответствии с ответом на этот вопрос). Этот метод не является сверхбезопасным; По сути, скрипт может получить доступ к секретной информации, поэтому любой, кто имеет полный системный доступ, имеет скрипт и связанные с ним файлы и может получить к ним доступ. То, что это делает, идентифицирует данные от случайной проверки и оставляет файлы данных в безопасности, если они проверяются по отдельности или вместе без сценария.
Моя мотивация для этого – проект, который опрашивает некоторые из моих банковских счетов для мониторинга транзакций – мне нужно, чтобы он работал в фоновом режиме без повторного ввода паролей каждую минуту или две.
Просто вставьте этот код в начало вашего скрипта, измените saltSeed, а затем используйте store () retrieve () и require () в своем коде по мере необходимости:
from getpass import getpass
from pbkdf2 import PBKDF2
from Crypto.Cipher import AES
import os
import base64
import pickle
### Settings ###
saltSeed = 'mkhgts465wef4fwtdd' # MAKE THIS YOUR OWN RANDOM STRING
PASSPHRASE_FILE = './secret.p'
SECRETSDB_FILE = './secrets'
PASSPHRASE_SIZE = 64 # 512-bit passphrase
KEY_SIZE = 32 # 256-bit key
BLOCK_SIZE = 16 # 16-bit blocks
IV_SIZE = 16 # 128-bits to initialise
SALT_SIZE = 8 # 64-bits of salt
### System Functions ###
def getSaltForKey(key):
return PBKDF2(key, saltSeed).read(SALT_SIZE) # Salt is generated as the hash of the key with it's own salt acting like a seed value
def encrypt(plaintext, salt):
''' Pad plaintext, then encrypt it with a new, randomly initialised cipher. Will not preserve trailing whitespace in plaintext!'''
# Initialise Cipher Randomly
initVector = os.urandom(IV_SIZE)
# Prepare cipher key:
key = PBKDF2(passphrase, salt).read(KEY_SIZE)
cipher = AES.new(key, AES.MODE_CBC, initVector) # Create cipher
return initVector cipher.encrypt(plaintext ' '*(BLOCK_SIZE - (len(plaintext) % BLOCK_SIZE))) # Pad and encrypt
def decrypt(ciphertext, salt):
''' Reconstruct the cipher object and decrypt. Will not preserve trailing whitespace in the retrieved value!'''
# Prepare cipher key:
key = PBKDF2(passphrase, salt).read(KEY_SIZE)
# Extract IV:
initVector = ciphertext[:IV_SIZE]
ciphertext = ciphertext[IV_SIZE:]
cipher = AES.new(key, AES.MODE_CBC, initVector) # Reconstruct cipher (IV isn't needed for edecryption so is set to zeros)
return cipher.decrypt(ciphertext).rstrip(' ') # Decrypt and depad
### User Functions ###
def store(key, value):
''' Sore key-value pair safely and save to disk.'''
global db
db[key] = encrypt(value, getSaltForKey(key))
with open(SECRETSDB_FILE, 'w') as f:
pickle.dump(db, f)
def retrieve(key):
''' Fetch key-value pair.'''
return decrypt(db[key], getSaltForKey(key))
def require(key):
''' Test if key is stored, if not, prompt the user for it while hiding their input from shoulder-surfers.'''
if not key in db: store(key, getpass('Please enter a value for "%s":' % key))
### Setup ###
# Aquire passphrase:
try:
with open(PASSPHRASE_FILE) as f:
passphrase = f.read()
if len(passphrase) == 0: raise IOError
except IOError:
with open(PASSPHRASE_FILE, 'w') as f:
passphrase = os.urandom(PASSPHRASE_SIZE) # Random passphrase
f.write(base64.b64encode(passphrase))
try: os.remove(SECRETSDB_FILE) # If the passphrase has to be regenerated, then the old secrets file is irretrievable and should be removed
except: pass
else:
passphrase = base64.b64decode(passphrase) # Decode if loaded from already extant file
# Load or create secrets database:
try:
with open(SECRETSDB_FILE) as f:
db = pickle.load(f)
if db == {}: raise IOError
except (IOError, EOFError):
db = {}
with open(SECRETSDB_FILE, 'w') as f:
pickle.dump(db, f)
### Test (put your code here) ###
require('id')
require('password1')
require('password2')
print
print 'Stored Data:'
for key in db:
print key, retrieve(key) # decode values on demand to avoid exposing the whole database in memory
# DO STUFF
Безопасность этого метода была бы значительно улучшена, если бы для секретных файлов были установлены разрешения os, чтобы позволить только самому сценарию их читать, и если сам сценарий был скомпилирован и помечен как исполняемый (не читаемый). Некоторые из них могут быть автоматизированы, но я не беспокоился. Вероятно, потребуется настроить пользователя для сценария и запустить сценарий от имени этого пользователя (и установить право собственности на файлы сценария для этого пользователя).
Я буду рад любым предложениям, критике или другим уязвимым местам, о которых может подумать каждый. Я довольно новичок в написании криптографического кода, поэтому то, что я сделал, почти наверняка можно улучшить.
Вариант 3: файлы конфигурации
Это очень похоже на переменные среды, но вы читаете секреты из текстового файла. Я все еще нахожу переменные среды более гибкими для таких вещей, как инструменты развертывания и серверы непрерывной интеграции. Если вы решите использовать файл конфигурации, Python поддерживает несколько форматов в стандартной библиотеке, например JSON, INI, netrc и XML.
Три вещи, которые следует учитывать при использовании файлов конфигурации:
- Где файл? Возможно расположение по умолчанию, например
~/.my_app
, и параметр командной строки для использования другого расположения. - Убедитесь, что другие пользователи не могут прочитать файл.
- Очевидно, не фиксируйте файл конфигурации в исходном коде. Возможно, вы захотите зафиксировать шаблон, который пользователи могут скопировать в свой домашний каталог.
Как делать не надо
Всем знакома концепция «временного скриптика». Вот буквально только данные по-быстрому распарсить из базы и удалить. А потом внезапно выясняется, что скрипт уже из dev-зоны мигрировал куда-то в продакшен. И тут начинают всплывать неприятные сюрпризы от изначальной «одноразовости».
Чаще всего встречается вариант в стиле:
db_login = 'john.doe'
password = 'password!'
Проблема в том, что здесь пароль светится в открытом виде и достаточно просто обнаруживается среди залежей старых скриптов автоматическим поиском. Чуть более сложный вариант идет по пути security through obscurity, с хранением пароля в зашифрованном виде прямо в коде.
При этом расшифровка обратно должна выполняться тут же, иначе клиент не сможет предъявить этот пароль серверной стороне. Такой способ спасет максимум от случайного взгляда, но любой серьезный разбор кода вручную позволит без проблем вытащить секретный ключ. Код ниже спасет только от таких «shoulder surfers»:
>>> import base64
>>> print base64.b64encode("password")
cGFzc3dvcmQ=
>>> print base64.b64decode("cGFzc3dvcmQ=")
password
Самый неприятный сценарий — использования систем контроля версии, например git, для таких файлов с чувствительной информацией. Даже, если автор решит вычистить все пароли — они останутся в истории репозитория. Фактически, если вы запушили в git файл с секретными данными — можете автоматически считать их скомпрометированными и немедленно начинать процедуру замены всех затронутых credentials.
Ключи параметров ведения журнала
- /L – получить только список, в данном случае Robust File Copy Utility файлы не копирует, не удаляет, не помечается метками времени.
- /X – Сообщать обо всех дополнительных файлах, а не только о выбранных.
- /V – Подробный вывод с указанием пропущенных файлов.
- /TS – Включать в вывод меток времени исходных файлов.
- /FP – Включать в вывод полные пути файлов.
- /BYTES – Печатать размеры файлов в байтах.
- /NS – Режим без размера, у вас не будет заноситься информация, о размерах файлов в журнал.
- /NC – Режим без класса, не заносить в журнал классы файлов.
- /NFL – Режим без списка файлов, не заносить в журнал имена файлов.
- /NDL – Режим без списка папок, не заносить в журнал имена папок.
- /NP – Режим без хода процесса, не отображать число скопированных процентов.
- /ETA – Показывать оценку времени окончания копирования файлов.
- /LOG:файл – Производить запись состояния в файл журнала (перезаписывать существующий журнал).
- /LOG :файл – Производить запись состояния в файл журнала (добавлять к существующему журналу).
- /UNILOG:файл – Производить запись состояния в файл журнала в формате Юникод (перезаписывать существующий журнал).
- /UNILOG :файл – Производить запись состояния в файл журнала в формате Юникод (добавлять к существующему журналу).
- /TEE – Направлять выходные данные в окно консоли и в файл журнала.
- /NJH – Без заголовка задания.
- /NJS – Без сведений о задании.
- /UNICODE – Состояние вывода в формате Юникод.
Команда copy
Одной из наиболее часто повторяющихся задач при работе на компьютере является копирование и перемещение файлов из одного места в другое. Для копирования одного или нескольких файлов используется команда COPY.
Синтаксис этой команды:
COPY [/A|/B] источник [/A|/B] [ источник [/A|/B] [ ...]] [результат [/A|/B]] [/V][/Y|/–Y]
Краткое описание параметров и ключей команды COPY приведено в таблице.
Таблица 1.1. Параметры и ключи команды COPY | |
Параметр | Описание |
источник | Имя копируемого файла или файлов |
/A | Файл является текстовым файлом ASCII, то есть конец файла обозначается символом с кодом ASCII 26 (<Ctrl> <Z>) |
/B | Файл является двоичным. Этот ключ указывает на то, что интерпретатор команд должен при копировании считывать из источника число байт, заданное размером в каталоге копируемого файла |
результат | Каталог для размещения результата копирования и/или имя создаваемого файла |
/V | Проверка правильности копирования путем сравнения файлов после копирования |
/Y | Отключение режима запроса подтверждения на замену файлов |
/-Y | Включение режима запроса подтверждения на замену файлов |
Приведем примеры использования команды COPY.
Копирование файла abc.txt из текущего каталога в каталог D:PROGRAM под тем же именем:
COPY abc.txt D:PROGRAM
Копирование файла abc.txt из текущего каталога в каталог D:PROGRAM под новым именем def.txt:
COPY abc.txt D:PROGRAMdef.txt
Копирование всех файлов с расширением txt с диска A: в каталог ‘Мои документы’ на диске C:
COPY A:*.txt "C:Мои документы"
Если не задать в команде целевой файл, то команда COPY создаст копию файла-источника с тем же именем, датой и временем создания, что и исходный файл, и поместит новую копию в текущий каталог на текущем диске. Например, для того, чтобы скопировать все файлы из корневого каталога диска A: в текущий каталог, достаточно выполнить такую краткую команду:
COPY A:*.*
В качестве источника или результата при копировании можно указывать имена не только файлов, но и устройств компьютера. Например, для того, чтобы распечатать файл abc.txt на принтере, можно воспользоваться командой копирования этого файла на устройство PRN: COPY abc.txt PRN
Другой интересный пример: создадим новый текстовый файл и запишем в него информацию, без использования текстового редактора. Для этого достаточно ввести команду COPY CON my.txt, которая будет копировать то, что вы набираете на клавиатуре, в файл my.txt (если этот файл существовал, то он перезапишется, иначе — создастся). Для завершения ввода необходимо ввести символ конца файла, то есть нажать клавиши <Ctrl> <Z>.
Команда COPY может также объединять (склеивать) нескольких файлов в один. Для этого необходимо указать единственный результирующий файл и несколько исходных. Это достигается путем использования групповых знаков (? и *) или формата файл1 файл2 файл3. Например, для объединения файлов 1.txt и 2.txt в файл 3.txt можно задать следующую команду:
COPY 1.txt 2.txt 3.txt
Объединение всех файлов с расширением dat из текущего каталога в один файл all.dat может быть произведено так:
COPY /B *.dat all.dat
Ключ /B здесь используется для предотвращения усечения соединяемых файлов, так как при комбинировании файлов команда COPY по умолчанию считает файлами текстовыми.
Если имя целевого файла совпадает с именем одного из копируемых файлов (кроме первого), то исходное содержимое целевого файла теряется. Если имя целевого файла опущено, то в его качестве используется первый файл из списка. Например, команда COPY 1.txt 2.txt добавит к содержимому файла 1.txt содержимое файла 2.txt.
COPY /B 1.txt ,,
Здесь запятые указывают на пропуск параметра приемника, что и приводит к требуемому результату.
Команда COPY имеет и свои недостатки. Например, с ее помощью нельзя копировать скрытые и системные файлы, файлы нулевой длины, файлы из подкаталогов. Кроме того, если при копировании группы файлов COPY встретит файл, который в данный момент нельзя скопировать (например, он занят другим приложением), то процесс копирования полностью прервется, и остальные файлы не будут скопированы.
Команда dir
Еще одной очень полезной командой является DIR [диск:][путь][имя_файла] [ключи], которая используется для вывода информации о содержимом дисков и каталогов. Параметр [диск:][путь] задает диск и каталог, содержимое которого нужно вывести на экран. Параметр [имя_файла] задает файл или группу файлов, которые нужно включить в список. Например, команда
DIR C:*.bat
выведет на экран все файлы с расширением bat в корневом каталоге диска C:. Если задать эту команду без параметров, то выводится метка диска и его серийный номер, имена (в коротком и длинном вариантах) файлов и подкаталогов, находящихся в текущем каталоге, а также дата и время их последней модификации.
Том в устройстве C имеет метку PHYS1_PART2 Серийный номер тома: 366D-6107 Содержимое папки C:aditor . <ПАПКА> 25.01.00 17:15 . .. <ПАПКА> 25.01.00 17:15 .. TEMPLT02 DAT 227 07.08.98 1:00 templt02.dat UNINST1 000 1 093 02.03.99 8:36 UNINST1.000 HILITE DAT 1 082 18.09.98 18:55 hilite.dat TEMPLT01 DAT 48 07.08.98 1:00 templt01.dat UNINST0 000 40 960 15.04.98 2:08 UNINST0.000 TTABLE DAT 357 07.08.98 1:00 ttable.dat ADITOR EXE 461 312 01.12.99 23:13 aditor.exe README TXT 3 974 25.01.00 17:26 readme.txt ADITOR HLP 24 594 08.10.98 23:12 aditor.hlp ТЕКСТО~1 TXT 0 11.03.01 9:02 Текстовый файл.txt 11 файлов 533 647 байт 2 папок 143 261 696 байт свободно
С помощью ключей команды DIR можно задать различные режимы расположения, фильтрации и сортировки. Например, при использовании ключа /W перечень файлов выводится в широком формате с максимально возможным числом имен файлов или каталогов на каждой строке. Например:
Том в устройстве C имеет метку PHYS1_PART2 Серийный номер тома: 366D-6107 Содержимое папки C:aditor [.] [..] TEMPLT02.DAT UNINST1.000 HILITE.DAT TEMPLT01.DAT UNINST0.000 TTABLE.DAT ADITOR.EXE README.TXT ADITOR.HLP ТЕКСТО~1.TXT 11 файлов 533 647 байт 2 папок 143 257 600 байт свободно
С помощью ключа /A[[:]атрибуты] можно вывести имена только тех каталогов и файлов, которые имеют заданные атрибуты (R — “Только чтение”, A — “Архивный”, S — “Системный”, H — “Скрытый”, префикс “–” имеет значение НЕ). Если ключ /A используется более чем с одним значением атрибута, будут выведены имена только тех файлов, у которых все атрибуты совпадают с заданными.
DIR C: /A:HS
а для вывода всех файлов, кроме скрытых — команду
DIR C: /A:-H
Отметим здесь, что атрибуту каталога соответствует буква D, то есть для того, чтобы, например, вывести список всех каталогов диска C:, нужно задать команду
DIR C: /A:D
Ключ /O[[:]сортировка] задает порядок сортировки содержимого каталога при выводе его командой DIR. Если этот ключ опущен, DIR печатает имена файлов и каталогов в том порядке, в котором они содержатся в каталоге. Если ключ /O задан, а параметр сортировка не указан, то DIR выводит имена в алфавитном порядке.
В параметре сортировка можно использовать следующие значения: N — по имени (алфавитная), S — по размеру (начиная с меньших), E — по расширению (алфавитная), D — по дате (начиная с более старых), A — по дате загрузки (начиная с более старых), G — начать список с каталогов.
Ключ /S означает вывод списка файлов из заданного каталога и его подкаталогов.
Ключ /B перечисляет только названия каталогов и имена файлов (в длинном формате) по одному на строку, включая расширение. При этом выводится только основная информация, без итоговой. Например:
templt02.dat UNINST1.000 hilite.dat templt01.dat UNINST0.000 ttable.dat aditor.exe readme.txt aditor.hlp Текстовый файл.txt
Команда move
Синтаксис команды для перемещения одного или более файлов имеет вид:
MOVE [/Y|/–Y] [диск:][путь]имя_файла1[,...] результирующий_файл
Синтаксис команды для переименования папки имеет вид:
MOVE [/Y|/–Y] [диск:][путь]каталог1 каталог2
Здесь параметр результирующий_файл задает новое размещение файла и может включать имя диска, двоеточие, имя каталога, либо их сочетание. Если перемещается только один файл, допускается указать его новое имя. Это позволяет сразу переместить и переименовать файл. Например,
MOVE "C:Мои документысписок.txt" D:list.txt
Если указан ключ /-Y, то при создании каталогов и замене файлов будет выдаваться запрос на подтверждение. Ключ /Y отменяет выдачу такого запроса.
CD | COPY | XCOPY | DIR | MKDIR | RMDIR | DEL | REN | MOVE
Команда xcopy
Указанные при описании команды COPY проблемы можно решить с помощью команды XCOPY, которая предоставляет намного больше возможностей при копировании. Необходимо отметить, правда, что XCOPY может работать только с файлами и каталогами, но не с устройствами.
Синтаксис этой команды:
XCOPY источник [результат] [ключи]
Команда XCOPY имеет множество ключей, мы коснемся лишь некоторых из них. Ключ /D[:[дата]] позволяет копировать только файлы, измененные не ранее указанной даты. Если параметр дата не указан, то копирование будет производиться только если источник новее результата. Например, команда
XCOPY "C:Мои документы*.*" "D:BACKUPМои документы" /D
скопирует в каталог ‘D:BACKUPМои документы’ только те файлы из каталога ‘C:Мои документы’, которые были изменены со времени последнего подобного копирования или которых вообще не было в ‘D:BACKUPМои документы’.
Ключ /S позволяет копировать все непустые подкаталоги в каталоге-источнике. С помощью же ключа /E можно копировать вообще все подкаталоги, включая и пустые.
Если указан ключ /C, то копирование будет продолжаться даже в случае возникновения ошибок. Это бывает очень полезным при операциях копирования, производимых над группами файлов, например, при резервном копировании данных.
Ключ /I важен для случая, когда копируются несколько файлов, а файл назначения отсутствует. При задании этого ключа команда XCOPY считает, что файл назначения должен быть каталогом. Например, если задать ключ /I в команде копирования всех файлов с расширением txt из текущего каталога в несуществующий еще подкаталог TEXT,
XCOPY *.txt TEXT /I
то подкаталог TEXT будет создан без дополнительных запросов.
Ключи /Q, /F и /L отвечают за режим отображения при копировании. При задании ключа /Q имена файлов при копировании не отображаются, ключа /F — отображаются полные пути источника и результата. Ключ /L обозначает, что отображаются только файлы, которые должны быть скопированы (при этом само копирование не производится).
С помощью ключа /H можно копировать скрытые и системные файлы, а с помощью ключа /R — заменять файлы с атрибутом “Только для чтения”. Например, для копирования всех файлов из корневого каталога диска C: (включая системные и скрытые) в каталог SYS на диске D:, нужно ввести следующую команду:
XCOPY C:*.* D:SYS /H
Ключ /T позволяет применять XCOPY для копирования только структуры каталогов источника, без дублирования находящихся в этих каталогах файлов, причем пустые каталоги и подкаталоги не включаются. Для того, чтобы все же включить пустые каталоги и подкаталоги, нужно использовать комбинацию ключей /T /E.
Используя XCOPY можно при копировании обновлять только уже существующие файлы (новые файлы при этом не записываются). Для этого применяется ключ /U. Например, если в каталоге C:2 находились файлы a.txt и b.txt, а в каталоге C:1 — файлы a.txt, b.txt, c.txt и d.txt, то после выполнения команды
XCOPY C:1 C:2 /U
в каталоге C:2 по-прежнему останутся лишь два файла a.txt и b.txt, содержимое которых будет заменено содержимым соответствующих файлов из каталога C:1.Если с помощью XCOPY копировался файл с атрибутом “Только для чтения”, то по умолчанию у файла-копии этот атрибут снимется. Для того, чтобы копировать не только данные, но и полностью атрибуты файла, необходимо использовать ключ /K.
Ключи /Y и /-Y определяют, нужно ли запрашивать подтверждение перед заменой файлов при копировании. /Y означает, что такой запрос нужен, /-Y — не нужен.
Обзор robocopy gui utility ver. 3.1
Давайте я бегло покажу, что из себя представляет данная программа. Сам графический интерфейс очень простой, так и должно быть. На первой вкладке вы увидите два действия:
- Первое, это нужно через “Source Path выбрать, что мы будем копировать”
- Второе действие, это в “Target Path мы задаем, куда мы будем переносить данные, при желании вы можете смонтировать сетевой диск, через пункт “Map Drive””
На вкладке “Copy Options”, вы увидите уже знакомые параметры использования Robocopy, тут есть и ключи /SEC для переноса прав и команда /MOVE, которую мы применяли для вырезания файлов и многое другое. Тут же вы задаете количество потоков копирования.
Вкладка “Drive Mapping” поможет присоединить сетевой диск, тут вы указываете ip-адрес или DNS имя сервера, и учетные данные для подключения.
Вкладка “Filters” позволит вам указать, что именно нужно переносить и сделать фильтрацию, например, не переносить файлы длина которых в имени составляет более 256 символов, или только txt файлы.
Вкладка “Logging” задает параметры ведения логирования вашего задания.
Вкладка “Monitoring Options” будет полезна для наблюдения за источником копирования, в случае проблем, все можно идентифицировать и перезапустить.
Пример
Создадим текстовый файл example.txt и сохраним его в рабочей директории.
Следующий код используется для его открытия.
f =open('example.txt','r')
fp =open('C:/xyz.txt','r')
В этом примере f — переменная-указатель на файл example.txt.
Следующий код используется для вывода содержимого файла и информации о нем.
>>>print(*f)
This is a text file.>>>print(f)<_io.TextIOWrapper name='example.txt' mode='r' encoding='cp1252'>
Стоит обратить внимание, что в Windows стандартной кодировкой является cp1252, а в Linux — utf-08.
Текущая позиция в файлах python
В Python возможно узнать текущую позицию в файле с помощью функции tell(). Таким же образом можно изменить текущую позицию командой seek().
Пример
>>> f =open('example.txt')>>> f.read(4)
This
>>> f.tell()4>>> f.seek(0,0)
Функция read()
Функция read() используется для чтения содержимого файла после открытия его в режиме чтения (r).
Синтаксис
file.read(size)
Где,
file
= объект файлаsize
= количество символов, которые нужно прочитать. Если не указать, то файл прочитается целиком.
Пример
>>> f =open('example.txt','r')>>> f.read(7)'This is '
Интерпретатор прочитал 7 символов файла и если снова использовать функцию read(), то чтение начнется с 8-го символа.
>>> f.read(7)' a text'
Функция readline()
Функция readline() используется для построчного чтения содержимого файла. Она используется для крупных файлов. С ее помощью можно получать доступ к любой строке в любой момент.
Пример
Создадим файл test.txt с нескольким строками:
This is line1.
This is line2.
This is line3.
Посмотрим, как функция readline() работает в test.txt.
>>> x =open('test.txt','r')>>> x.readline()
This is line1.>>> x.readline(2)
This is line2.>>> x.readlines()['This is line1.','This is line2.','This is line3.']
Обратите внимание, как в последнем случае строки отделены друг от друга.
Функция rename()
Функция rename() используется для переименовывания файлов в Python. Для ее использования сперва нужно импортировать модуль os.
Синтаксис следующий.
import os
os.rename(src,dest)
Где,
src
= файл, который нужно переименоватьdest
= новое имя файла
Пример
>>>import os
>>>>>> os.rename("xyz.txt","abc.txt")
Функция write()
Функция write() используется для записи в файлы Python, открытые в режиме записи.
Если пытаться открыть файл, которого не существует, в этом режиме, тогда будет создан новый.
Синтаксис
file.write(string)
Пример
Предположим, файла xyz.txt не существует. Он будет создан при попытке открыть его в режиме чтения.
>>> f =open('xyz.txt','w')>>> f.write('Hello n World')
Hello
World
>>> f.close()
Метод close()
После открытия файла в Python его нужно закрыть. Таким образом освобождаются ресурсы и убирается мусор. Python автоматически закрывает файл, когда объект присваивается другому файлу.
Существуют следующие способы:
Способ №1
Проще всего после открытия файла закрыть его, используя метод close().
f =open('example.txt','r')
f.close()
После закрытия этот файл нельзя будет использовать до тех пор, пока заново его не открыть.
Способ №2
Также можно написать try/finally, которое гарантирует, что если после открытия файла операции с ним приводят к исключениям, он закроется автоматически.
Без него программа завершается некорректно.
Вот как сделать это исключение:
f =open('example.txt','r')try:finally:
f.close()
Файл нужно открыть до инструкции try
, потому что если инструкция open
сама по себе вызовет ошибку, то файл не будет открываться для последующего закрытия.
Этот метод гарантирует, что если операции над файлом вызовут исключения, то он закроется до того как программа остановится.
Способ №3