Слишком длинный список аргументов для команд rm, cp, mv


629

У меня есть несколько сотен PDF-файлов в каталоге в UNIX. Названия PDF-файлов действительно длинные (около 60 символов).

Когда я пытаюсь удалить все PDF-файлы вместе, используя следующую команду:

rm -f *.pdf

Я получаю следующую ошибку:

/bin/rm: cannot execute [Argument list too long]

Каково решение этой ошибки? Возникает ли эта ошибка для mvи cpкоманды, а? Если да, как решить для этих команд?


21
Вы можете найти эту ссылку полезной
another.anon.coward


1
Также это может быть актуально http://mywiki.wooledge.org/BashFAQ/095
Лоренцо Белли

4
@jww: И я продолжал так много лет думать, что bash подпадает под «программные инструменты, обычно используемые программистами» - категорию, вопросы которой можно задавать здесь!
Вики

@Nik - Добавление "... в сценарии" не является убедительным. Когда проблема сводится к примеру Minimal, Complete и Verifiable , это просто вопрос о том, как выполнить команду. Мои извинения, если я упускаю что-то очевидное.
jww

Ответы:


876

Причина этого заключается в том, что bash фактически расширяет звездочку до каждого соответствующего файла, создавая очень длинную командную строку.

Попробуй это:

find . -name "*.pdf" -print0 | xargs -0 rm

Предупреждение: это рекурсивный поиск, который также найдет (и удалит) файлы в подкаталогах. Придерживайтесь -fкоманды rm, только если вы уверены, что не хотите подтверждения.

Чтобы сделать команду нерекурсивной, вы можете сделать следующее:

find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm

Другой вариант - использовать -deleteфлаг поиска :

find . -name "*.pdf" -delete

7
Нет, xargsспециально разбивает список и при необходимости выдает несколько команд.
tripleee

7
@Dennis: -maxdepth 1должен быть первым аргументом после пути.
Бартон Читтенден

54
Find имеет -deleteфлаг для удаления файлов, которые он находит, и даже если бы он этого не сделал, все равно было бы лучше использовать -execдля выполнения rm, чем вызывать xargs (который теперь представляет собой 3 процесса и конвейер вместо одного процесса с -deleteили 2 процесса с -exec).
Scragar

3
@ ÉdouardLopez ... Но это чтение ввода, разделенного NULL. И в целом dangerous (broken, exploitable, etc.), это довольно смешно. Несомненно, вы должны быть осторожны при использовании xargs, но это не совсем так eval/evil.
Восстановите Монику, пожалуйста,

4
@scragar При -execвызове rmчисло процессов будет равно 1 + количество файлов, хотя число одновременных процессов из этого может быть 2 (возможно, find выполнит процессы rm одновременно). Количество используемых процессов xargsбудет значительно сокращено до 2 + n, где n - это некоторое число процессов, которое меньше количества файлов (скажем, число файлов / 10, хотя, вероятно, больше в зависимости от длины путей). Предполагая, что find выполняет удаление напрямую, использование -deleteдолжно быть единственным процессом, который будет вызван.
невралмер

397

ТЛ; др

Это ограничение ядра на размер аргумента командной строки. forВместо этого используйте цикл.

Происхождение проблемы

Это системная проблема, связанная execveи ARG_MAXпостоянная. Об этом много документации (см. Man execve , вики Debian ).

По сути, расширение создает команду (с ее параметрами), которая превышает ARG_MAXпредел. На ядре 2.6.23ограничение было установлено на 128 kB. Эта константа была увеличена, и вы можете получить ее значение, выполнив:

getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic

Решение: использование forLoop

Используйте forцикл, как это рекомендуется для BashFAQ / 095, и нет никаких ограничений, за исключением объема ОЗУ / памяти:

Пробный запуск, чтобы убедиться, что он удалит то, что вы ожидаете:

for f in *.pdf; do echo rm "$f"; done

И выполнить это:

for f in *.pdf; do rm "$f"; done

Также это переносимый подход, поскольку у glob сильное и согласованное поведение среди оболочек ( часть спецификации POSIX ).

Примечание. Как отмечается в нескольких комментариях, это действительно медленнее, но более приемлемо, поскольку может адаптировать более сложные сценарии, например, когда требуется выполнить больше, чем одно действие.

Решение: Использование find

Если вы настаиваете, вы можете использовать, findно на самом деле не используйте xargs, поскольку он «опасен (сломан, может использоваться и т. Д.) При чтении ввода, не разделенного NUL» :

find . -maxdepth 1 -name '*.pdf' -delete 

Использование -maxdepth 1 ... -deleteвместо -exec rm {} +позволяет findпросто выполнять необходимые системные вызовы без использования внешнего процесса, следовательно, быстрее (благодаря комментарию @chepner ).

Ссылки


31
Отличный ответ, так нужно отвечать на все вопросы SO. Спасибо!
Том

1
+1 за упоминание forпетли. Я использовал findраньше, но я всегда ищу, как это сделать, потому что я все время забываю варианты и т. Д. forКажется, легче вспомнить ИМХО
Роберт Дандон

3
Использовал это как for f in *; do rm "$f"; doneработу как очарование
abdul qayyum

3
find -execРешение представляется гораздо быстрее , чем forцикл.
три

2
Пять лет спустя в 4.15.0 ( 4.15.0-1019-gcpесли быть точным), и предел все еще в 2097152. Интересно, что поиск ARG_MAX в git-репозитории linux дает результат, показывающий, что ARG_MAX находится в 131702.
Мэтт М.

181

findимеет -deleteдействие:

find . -maxdepth 1 -name '*.pdf' -delete

4
Это все равно вернет «Список аргументов слишком длинный». По крайней мере, для меня это так. Использование xargs, согласно ответу Денниса, работает как задумано.
Серхио

7
Это звучит как ошибка в поиске.
ThiefMaster

3
У @Sergio была та же самая проблема, это было вызвано отсутствующими кавычками вокруг имени.
августа

аааа, почему инструмент для поиска вещей даже имеет переключатель для удаления? неужели только я считаю ненужным, мягко говоря, и опасным.
mathreadler

2
@mathreadler Рассматривает тот факт, что распространенным вариантом использования -execявляется удаление нескольких файлов. -exec rm {} +будет делать то же самое, но все еще требует запуска хотя бы одного внешнего процесса. -deleteпозволяет findпросто выполнить необходимые системные вызовы самостоятельно, без использования внешней оболочки.
chepner

21

Другой ответ состоит в том, чтобы заставить xargsобрабатывать команды в пакетном режиме. Например, к deleteфайлам 100за раз, cdв каталог и запустите это:

echo *.pdf | xargs -n 100 rm


4
Для удаления команды в Linux, которая может быть катастрофой, если вы инженер и ввели ошибку, я считаю, что это «самый безопасный и я знаю, что происходит», это лучший вариант. Не то, что если вы пропустите ввод точки, ваша компания потерпит крах за одну минуту.
Искусственный

1
Как мы можем сделать это расширением по умолчанию для определенных команд? Существует множество «стандартных» команд linux, в которых известно, нужны ли они всем сразу или нет (например, «rm»)
user1212212

1
Обратите внимание, что это работает только там, где echoвстроена оболочка. Если вы в конечном итоге используете команду echo, вы все равно столкнетесь с ограничением аргументов программы.
Тоби Спейт

14

Или вы можете попробовать:

find . -name '*.pdf' -exec rm -f {} \;

Это также удаляет файлы из подкаталогов. Как это предотвратить?
Вики

@NikunjChauhan Добавить параметр -maxdepth:find . -maxdepth 1 -name '*.pdf' -exec rm -f {} \;
Джон Лин

Я не могу вставить параметр maxdepth
Вики

Эта опция может быть опцией только для Linux, как указано выше в ответе @ Dennis (выбранный ответ).
jvriesem

12

Если вы пытаетесь удалить очень большое количество файлов за один раз (сегодня я удалил каталог с 485 000+), вы, вероятно, столкнетесь с этой ошибкой:

/bin/rm: Argument list too long.

Проблема заключается в том, что когда вы набираете что-то вроде rm -rf *, то *заменяется списком каждого соответствующего файла, например, «rm -rf file1 file2 file3 file4» и так далее. Для хранения этого списка аргументов имеется относительно небольшой буфер памяти, и, если он заполнен, оболочка не выполнит программу.

Чтобы обойти эту проблему, многие люди используют команду find, чтобы найти каждый файл и передать их один за другим команде «rm», например так:

find . -type f -exec rm -v {} \;

Моя проблема в том, что мне нужно было удалить 500 000 файлов, и это заняло слишком много времени.

Я наткнулся на гораздо более быстрый способ удаления файлов - команда «find» имеет встроенный флаг «-delete»! Вот что я в итоге использовал:

find . -type f -delete

Используя этот метод, я удалял файлы со скоростью около 2000 файлов в секунду - намного быстрее!

Вы также можете показать имена файлов при их удалении:

find . -type f -print -delete

... или даже показать, сколько файлов будет удалено, а затем время, необходимое для их удаления:

root@devel# ls -1 | wc -l && time find . -type f -delete
100000
real    0m3.660s
user    0m0.036s
sys     0m0.552s

Спасибо. Я сделал, sudo find . -type f -deleteчтобы удалить около 485 тысяч файлов, и это сработало для меня. Прошло около 20 секунд.
Найджел Олдертон

11

Вы можете попробовать это:

for f in *.pdf
do
  rm $f
done

РЕДАКТИРОВАТЬ: комментарий ThiefMaster предлагает мне не раскрывать такую ​​опасную практику для джедаев молодой оболочки, поэтому я добавлю более «более безопасную» версию (ради сохранения вещей, когда у кого-то есть файл «-rf. ..Pdf»)

echo "# Whooooo" > /tmp/dummy.sh
for f in '*.pdf'
do
   echo "rm -i $f" >> /tmp/dummy.sh
done

После запуска вышеприведенного, просто откройте файл /tmp/dummy.sh в вашем фаворе. редактировать и проверять каждую строку на наличие опасных имен файлов, комментируя их, если они найдены.

Затем скопируйте скрипт dummy.sh в ваш рабочий каталог и запустите его.

Все это по соображениям безопасности.


5
Я думаю, что это будет действительно хорошо с файлом с именем, например,-rf .. .pdf
ThiefMaster

да, но, как правило, при использовании в оболочке издатель команды «должен» посмотреть, что он делает :). На самом деле я предпочитаю перенаправить в файл, а затем проверять каждую строку.
BigMike

2
Это не цитата "$ f". Это то, о чем говорил ThiefMaster. -rfимеет приоритет над -iвашей второй версией (без ручной проверки). И в принципе бесполезно для массового удаления, потому что подсказки для каждого файла.
Питер Кордес

7

Вы можете использовать массив bash:

files=(*.pdf)
for((I=0;I<${#files[@]};I+=1000)); do
    rm -f "${files[@]:I:1000}"
done

Таким образом, он будет стирать партиями по 1000 файлов за шаг.


2
Для большого количества файлов это выглядит значительно быстрее
Джеймс Токнелл


4

У команды rm есть ограничение на количество файлов, которые вы можете удалить одновременно.

Одна возможность, вы можете удалить их, используя несколько раз команды rm, основанные на ваших шаблонах файлов, например:

rm -f A*.pdf
rm -f B*.pdf
rm -f C*.pdf
...
rm -f *.pdf

Вы также можете удалить их с помощью команды find :

find . -name "*.pdf" -exec rm {} \;

3
Нет, rmне имеет такого ограничения на количество файлов, которые он будет обрабатывать (кроме этого он argcне может быть больше, чем INT_MAX). Это ограничение ядра на максимальный размер всего массива аргументов (поэтому длина имен файлов значительна).
Тоби Спейт

3

Если это имена файлов с пробелами или специальными символами, используйте:

find -maxdepth 1 -name '*.pdf' -exec rm "{}" \;

Это предложение ищет все файлы в текущем каталоге (-maxdepth 1) с расширением pdf (-name '* .pdf'), а затем удаляет каждый из них (-exec rm "{}").

Выражение {} заменяет имя файла, а "{}" задает имя файла в виде строки, включая пробелы или специальные символы.


Хотя этот фрагмент кода может решить вопрос, в том числе объяснение того, как и почему это решает проблему , действительно поможет улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос для читателей в будущем, а не только для того, кто спрашивает сейчас! Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются.
Тоби Спейт

Весь смысл в -execтом, что вы не вызываете оболочку. Цитаты здесь не делают абсолютно ничего полезного. (Они предотвращают любое расширение подстановочного знака и разбиение токена на строке в оболочке, в которой вы вводите эту команду, но строка {}не содержит пробельных символов или символов подстановки оболочки.)
tripleee

2

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

исходный каталог имел файлы ~ 3 lakcs

я использовал cp с опцией -r, и это сработало для меня

cp -r abc / def /

он скопирует все файлы из abc в def без предупреждения о слишком длинном списке аргументов


Я не знаю, почему кто-то отрицал это, даже не комментируя это (это политика, ребята!). Мне нужно было удалить все файлы внутри папки (обратите внимание, вопрос не относится к PDF-файлам), и для этого этот трюк работает хорошо, все, что нужно сделать в конце, - это воссоздать папку, которая была удалена вместе с Я использовал `rm -R / path / to / folder".
Томас Темпельманн

1
Это работает, потому что в случае с OP он использовал *, который расширился до огромного списка .pdf, давая каталог, который будет обрабатывать это внутренне, таким образом, не имея дело с проблемой OP. Я думаю, что по этой причине было отклонено. Он может быть недоступен для OP, если у него есть вложенный каталог или другие файлы (не pdf) в его каталоге
Alvein 23.10.15

2

Попробуйте это также. Если вы хотите удалить файлы / папки за 30/90 (+) или менее 30/90 (-) дней, вы можете использовать приведенные ниже команды ex

Пример: для 90 дней исключается выше после 90 дней удаления файлов / папок, это означает 91,92 .... 100 дней

find <path> -type f -mtime +90 -exec rm -rf {} \;

Пример: только для последних 30-дневных файлов, которые вы хотите удалить, используйте команду ниже (-)

find <path> -type f -mtime -30 -exec rm -rf {} \;

Если вы хотите посмотреть файлы более чем на 2 дня

find <path> -type f -mtime +2 -exec gzip {} \;

Если вы хотите видеть файлы / папки только за последний месяц. Пример:

find <path> -type f -mtime -30 -exec ls -lrt {} \;

Более 30 дней больше, чем только список файлов / папок. Например:

find <path> -type f -mtime +30 -exec ls -lrt {} \;

find /opt/app/logs -type f -mtime +30 -exec ls -lrt {} \;

2

Я удивлен, что здесь нет ulimitответов. Каждый раз, когда у меня возникает эта проблема, я оказываюсь здесь или здесь . Я понимаю, что это решение имеет ограничения, но, ulimit -s 65536похоже, часто помогает мне.


1

У меня была та же проблема с папкой, полной временных изображений, которая росла день ото дня, и эта команда помогла мне очистить папку

find . -name "*.png" -mtime +50 -exec rm {} \;

Разница с другими командами заключается в параметре mtime, который будет принимать только файлы старше X дней (в примере 50 дней)

Используя это несколько раз, уменьшая при каждом выполнении дневной диапазон, я смог удалить все ненужные файлы


1

Я знаю только способ обойти это. Идея состоит в том, чтобы экспортировать этот список файлов PDF в ваш файл. Затем разделите этот файл на несколько частей. Затем удалите файлы PDF, перечисленные в каждой части.

ls | grep .pdf > list.txt
wc -l list.txt

wc -l - подсчитать, сколько строк содержит list.txt. Когда у вас есть представление о том, как долго это происходит, вы можете разделить его пополам, вперёд или что-то в этом роде. Использование команды split -l Например, разбить его на 600 строк каждая.

split -l 600 list.txt

это создаст несколько файлов с именами xaa, xab, xac и т. д., в зависимости от того, как вы разделите его. Теперь, чтобы «импортировать» каждый список в этом файле в команду rm, используйте это:

rm $(<xaa)
rm $(<xab)
rm $(<xac)

Извините за мой плохой английский.


5
Если у вас есть файл с таким именем, pdf_format_sucks.docxон также будет удален ... ;-) Вы должны использовать правильное и точное регулярное выражение при подборе файлов pdf.
FooF

1
Лучше, но still_pdf_format_sucks.docxбудет удалено. Точка .в ".pdf"регулярном выражении соответствует любому символу. Я бы предложил "[.]pdf$"вместо .pdf.
FooF

1

Я столкнулся с этой проблемой несколько раз. Многие решения будут запускать rmкоманду для каждого отдельного файла, который необходимо удалить. Это очень неэффективно:

find . -name "*.pdf" -print0 | xargs -0 rm -rf

В итоге я написал скрипт на python для удаления файлов на основе первых 4 символов в имени файла:

import os
filedir = '/tmp/' #The directory you wish to run rm on 
filelist = (os.listdir(filedir)) #gets listing of all files in the specified dir
newlist = [] #Makes a blank list named newlist
for i in filelist: 
    if str((i)[:4]) not in newlist: #This makes sure that the elements are unique for newlist
        newlist.append((i)[:4]) #This takes only the first 4 charcters of the folder/filename and appends it to newlist
for i in newlist:
    if 'tmp' in i:  #If statment to look for tmp in the filename/dirname
        print ('Running command rm -rf '+str(filedir)+str(i)+'* : File Count: '+str(len(os.listdir(filedir)))) #Prints the command to be run and a total file count
        os.system('rm -rf '+str(filedir)+str(i)+'*') #Actual shell command
print ('DONE')

Это сработало очень хорошо для меня. Мне удалось очистить более 2 миллионов временных файлов в папке примерно за 15 минут. Я прокомментировал tar из небольшого фрагмента кода, чтобы любой, кто имеет минимальные знания Python или не обладал ими, мог манипулировать этим кодом.


1

И еще один:

cd  /path/to/pdf
printf "%s\0" *.[Pp][Dd][Ff] | xargs -0 rm

printfэто встроенная оболочка, и, насколько я знаю, она всегда была таковой. Теперь, учитывая, что printfэто не команда оболочки (а встроенная), она не подвержена " argument list too long ..." фатальной ошибке.

Таким образом, мы можем безопасно использовать его с шаблонами сглаживания оболочки, такими как *.[Pp][Dd][Ff], затем передаем по выводу ее rmкоманду remove ( ), xargsкоторая проверяет, соответствует ли она достаточному количеству имен файлов в командной строке, чтобы не пропустить rmкоманду, являющуюся оболочкой. команда.

Оператор \0in printfслужит пустым разделителем для имен файлов, которые затем обрабатываются xargsкомандой с использованием it ( -0) в качестве разделителя, поэтому rmон не завершается ошибкой, если в именах файлов есть пробелы или другие специальные символы.


1
Хотя этот фрагмент кода может решить вопрос, в том числе объяснение того, как и почему это решает проблему , действительно поможет улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос для читателей в будущем, а не только для того, кто спрашивает сейчас! Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются.
Тоби Спейт

В частности, если printfне встроенная оболочка, на нее распространяются те же ограничения.
Тоби Спейт

0

Вы можете создать временную папку, переместить все файлы и подпапки, которые вы хотите сохранить, во временную папку, затем удалить старую папку и переименовать временную папку в старую папку, попробуйте этот пример, пока вы не будете уверены, что все это работает:

mkdir testit
cd testit
mkdir big_folder tmp_folder
touch big_folder/file1.pdf
touch big_folder/file2.pdf
mv big_folder/file1,pdf tmp_folder/
rm -r big_folder
mv tmp_folder big_folder

rm -r big_folderне будут удалены все файлы в big_folderнезависимо от того , сколько. Вы просто должны быть очень осторожны, у вас сначала есть все файлы / папки, которые вы хотите сохранить, в данном случае это былоfile1.pdf


0

Удалить все *.pdfв каталоге/path/to/dir_with_pdf_files/

mkdir empty_dir        # Create temp empty dir

rsync -avh --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/

Удаление определенных файлов с rsyncпомощью подстановочного знака, вероятно, является самым быстрым решением, если у вас миллионы файлов. И это позаботится об ошибке, которую вы получаете.


(Необязательный шаг): DRY RUN. Чтобы проверить, что будет удалено без удаления. `

rsync -avhn --delete --include '*.pdf' empty_dir/ /path/to/dir_with_pdf_files/

, , ,

Нажмите rsync советы и хитрости для более rsync хаков


0

Я обнаружил, что для очень больших списков файлов (> 1e6) эти ответы были слишком медленными. Вот решение с использованием параллельной обработки в Python. Я знаю, я знаю, что это не Linux ... но ничего другого здесь не работает.

(Это спасло меня часы)

# delete files
import os as os
import glob
import multiprocessing as mp

directory = r'your/directory'
os.chdir(directory)


files_names = [i for i in glob.glob('*.{}'.format('pdf'))]

# report errors from pool

def callback_error(result):
    print('error', result)

# delete file using system command
def delete_files(file_name):
     os.system('rm -rf ' + file_name)

pool = mp.Pool(12)  
# or use pool = mp.Pool(mp.cpu_count())


if __name__ == '__main__':
    for file_name in files_names:
        print(file_name)
        pool.apply_async(delete_files,[file_name], error_callback=callback_error)

0

Я столкнулся с подобной проблемой, когда приложение создавало миллионы бесполезных файлов журналов, которые заполняли все иноды. Я прибег к «locate», собрал все файлы, «расположенные» d, в текстовый файл, а затем удалил их один за другим. Потребовалось время, но сделал работу!


Это довольно расплывчато и требует, чтобы вы установили его locateобратно, когда у вас осталось место на диске.
tripleee

-2

Немного более безопасная версия, чем использование xargs, также не рекурсивная: ls -p | grep -v '/$' | grep '\.pdf$' | while read file; do rm "$file"; done

Фильтрация наших каталогов здесь немного ненужна, так как «rm» не удалит его в любом случае, и его можно удалить для простоты, но зачем запускать что-то, что обязательно вернет ошибку?


3
Это вообще небезопасно и не работает с именами файлов с символами новой строки в них, чтобы указать на один очевидный угловой случай. Синтаксический анализls является распространенным антипаттерном, которого определенно следует избегать, и добавляет сюда ряд дополнительных ошибок. Это grep | grepпросто не очень элегантно.
tripleee

В любом случае, это не новая и экзотическая проблема, требующая комплексного решения. Ответы с findхорошими и хорошо задокументированы здесь и в других местах. См., Например, mywiki.wooledge.org, чтобы узнать больше об этой и смежных темах.
tripleee

-2

Использование GNU parallel ( sudo apt install parallel) очень просто

Он запускает многопоточные команды, где «{}» - переданный аргумент.

Например

ls /tmp/myfiles* | parallel 'rm {}'


Я не знаю, но я предполагаю, что это потому, что передача вывода lsнепосредственно другим командам является опасным антипаттерном, и тот факт, что расширение подстановочного знака вызовет тот же сбой при выполнении, lsкак и в оригинальной rmкоманде ,
Тоби Спейт

Для контекста об этом см. ParsingLs . И parallelделает некоторых людей, которые предпочитают избегать сложности, неудобными - если вы посмотрите под капот, это довольно непрозрачно. См. Ветку списка рассылки по адресу lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html между Стефаном (одним из серых бород Unix & Linux StackExchange ) и Оле Танге (автор Parallel). xargs -Pтакже паралеллизует, но делает это более простым и тупым способом с меньшим количеством движущихся частей, что делает его поведение намного легче предсказать и обдумать.
Чарльз Даффи

-2

Для удаления первых 100 файлов:

rm -rf 'ls | голова -100 '


2
Опасно (или это было бы, если бы вы использовали обратные кавычки, как это явно предусмотрено) - если какое-либо имя файла содержит метасимволы оболочки, включая пробелы, то результаты не будут такими, как вы предполагали.
Тоби Спейт

-5

Опция ниже кажется простой для этой проблемы. Я получил эту информацию из другой ветки, но она мне помогла.

for file in /usr/op/data/Software/temp/application/openpages-storage/*; do
    cp "$file" /opt/sw/op-storage/
done

Просто запустите приведенную выше одну команду, и она выполнит задачу.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.