Linux скопировать имена файлов

Команда cp: правильное копирование папок с файлами в *nix

В этой статье будут раскрыты некоторые неочевидные вещи связанные с использованием wildcards при копировании, неоднозначное поведение команды cp при копировании, а также способы позволяющие корректно копировать огромное количество файлов без пропусков и вылетов.

Допустим нам нужно скопировать всё из папки /source в папку /target.

Первое, что приходит на ум это:

Сразу исправим эту команду на:

Ключ -a добавит копирование всех аттрибутов, прав и добавит рекурсию. Когда не требуется точное воспроизведение прав достаточно ключа -r .

После копирования мы обнаружим, что скопировались не все файлы — были проигнорированы файлы начинающиеся с точки типа:

.profile
.local
.mc
и тому подобные.

Потому что wildcards обрабатывает shell ( bash в типовом случае). По умолчанию bash проигнорирует все файлы начинающиеся с точек, так как трактует их как скрытые. Чтобы избежать такого поведения нам придётся изменить поведение bash с помощью команды:

Чтобы это изменение поведения сохранилось после перезагрузки, можно сделать файл wildcard.sh c этой командой в папке /etc/profile.d (возможно в вашем дистрибутиве иная папка).

А если в директории-источнике нет файлов, то shell не сможет ничего подставить вместо звёздочки, и также копирование завершится с ошибкой. Против подобной ситуации есть опции failglob и nullglob . Нам потребуется выставить failglob , которая не даст команде выполниться. nullglob не подойдёт, так как она строку с wildcards не нашедшими совпадения преобразует в пустую строку (нулевой длины), что для cp вызовет ошибку.

Однако, если в папке тысячи файлов и больше, то от подхода с использованием wildcards стоит отказаться вовсе. Дело в том, что bash разворачивает wildcards в очень длинную командную строку наподобие:

cp -a /souce/a /source/b /source/c …… /target

На длину командной строки есть ограничение, которое мы можем узнать используя команду:

Получим максимальную длину командной строки в байтах:

…. Maximum length of command we could actually use: 2089314 ….

Итак, давайте будем обходиться вовсе без wildcards.

И тут мы столкнёмся с неоднозначностью поведения cp . Если папки /target не существует, то мы получим то, что нам нужно.

Однако, если папка target существует, то файлы будут скопированы в папку /target/source.

Не всегда мы можем удалить заранее папку /target, так как в ней могут быть нужные нам файлы и наша цель, допустим, дополнить файлы в /target файлами из /source.

Если бы папки источника и приёмника назывались одинаково, например, мы копировали бы из /source в /home/source, то можно было бы использовать команду:

Читайте также:  How to install windows drivers in linux

И после копирования файлы в /home/source оказались бы дополненными файлами из /source.

Такая вот логическая задачка: мы можем дополнить файлы в директории-приёмнике, если папки называются одинаково, но если они отличаются, то папка-исходник будет помещена внутрь приёмника. Как скопировать файлы из /source в /target с помощью cp без wildcards?

Чтобы обойти это вредное ограничение мы используем неочевидное решение:

Те кто хорошо знаком с DOS и Linux уже всё поняли: внутри каждой папки есть 2 невидимые папки «.» и «..», являющиеся псевдопапками-ссылками на текущую и вышестоящие директории.

  • При копировании cp проверяет существование и пытается создать /target/.
  • Такая директория существует и это есть /target
  • Файлы из /source скопированы в /target корректно.

Поведение этой команды однозначно. Всё отработает без ошибок вне зависимости от того миллион у вас файлов или их нет вовсе.

Выводы

Если нужно скопировать все файлы из одной папки в другую, не используем wildcards, вместо них лучше использовать cp в сочетании с точкой в конце папки-источника. Это скопирует все файлы, включая скрытые и не завалится при миллионах файлов или полном отсутствии файлов.

Послесловие

vmspike предложил аналогичный по результату вариант команды:

ВНИМАНИЕ: регистр буквы T имеет значение. Если перепутать, то получите полную белиберду: направление копирования поменяется.
Благодарности:

  • Компании RUVDS.COM за поддержку и возможность публикации в своем блоге на Хабре.
  • За изображение TripletConcept. Картинка очень большая и детальная, можно открыть в отдельном окне.

Источник

Скопировать имена всех файлов в папке в текстовый файл

Если вам оказалась полезна или просто понравилась эта статья, тогда не стесняйтесь — поддержите материально автора. Это легко сделать закинув денежек на Яндекс Кошелек № 410011416229354. Или на телефон +7 918-16-26-331.

Даже небольшая сумма может помочь написанию новых статей 🙂

Или поделитесь ссылкой на эту статью со своими друзьями.

Опубликовано: 07.06.2020 Последнее обновление этой статьи: 07.06.2020

В этой инструкция, как скопировать, в текстовый файл, имена всех файлов в папке.

В общем ничего сложного в этом и сделать это можно штатными средствами, которые есть в каждой операционной системе «из коробки». Далее, в этой статье, будут инструкции для двух самых распространенных ОС.

Имена всех файлов в папке в текстовый файл в ОС Windows

В ОС Windows нужно открыть «Командную строку» (файл cmd.exe). И там выполнить команду:

dir /b /a-d > filename.txt

Эта команда расшифровывается так:

  • dir — команда, которая показывает содержимое текущего или указанного каталога.
  • /b — опция команды, которая показывает, что нужно выводить только имена (без доп. информации).
  • /a-d — опция команды, которая показывает, что нужно выводить только файлы, без папок.
  • > filename.txt — перенаправление вывода команды в текстовый файл вместо экрана.

Вывод такой команды, в текстовом файле будет выглядеть вот так:

desktop.ini
dvazhdy.rozhdennyj.avi
filename.txt
logo-128.png
logo.jpg
logo.png
ls.txt

Более сложный вариант команды:

Читайте также:  How to create linux executable

dir D:\download /b /a-d > d:\temp\filename.txt

В этом варианте явным образом указаны пути, папки и файла.

Если нужно выбрать файлы из вложенных папок, тогда в команду нужно добавить опцию /s:

dir /b /a-d /s > filename.txt

Если нужно добавлять имена файлов к существующему содержимому файла (без перезаписи файла), тогда условие перенаправления нужно удвоить:

dir /b /a-d >> filename.txt

Имена всех файлов в папке в текстовый файл в ОС Linux

В ОС Linux есть аналогичная команда, которая тоже выполняется в терминале (консоли):

ls -p | grep -v ‘/$’ > filename.txt

Эта команда расшифровывается так:

  • ls — команда, которая показывает содержимое текущего или указанного каталога. Но, в отличии от команды Windows, в этой команде нет опции, которая «отсекает» имена папок. Поэтому нужно использовать обходной путь, для получения только имен файлов.
  • -p — опция, которая добавляет слэш к именам папок. Это нужно для того, чтобы «отсечь» имена папок.
  • | — перенаправление вывода команды ls в команду grep.
  • grep — команда, которая обрабатывает входной поток и выбирает из него элементы, по заданным условиям.
  • -v ‘/$’ — условие для удаления имен папок.
  • > filename.txt — перенаправление вывода команды в текстовый файл вместо экрана.

Таким образом получается следующее:

Команда ls выдает список файлов и папок и перенаправляет этот список в команду grep. Команда grep, удаляет из этого списка имена папок.

Если нужно выбрать файлы из вложенных папок, тогда в команду ls нужно добавить опцию /R:

ls -p -R | grep -v -e ‘/$’ -e ‘^./’ -e ‘^.:’ > filename.txt

Дополнительные OR (ИЛИ) условия команды grep нужны для удаления имен вложенных папок.

Иван Сухов, 2020 г.

Если вам оказалась полезна или просто понравилась эта статья, тогда не стесняйтесь — поддержите материально автора. Это легко сделать закинув денежек на Яндекс Кошелек № 410011416229354. Или на телефон +7 918-16-26-331.

Даже небольшая сумма может помочь написанию новых статей 🙂

Или поделитесь ссылкой на эту статью со своими друзьями.

Copyright digital.workshop 1999 — 2021.
Это произведение доступно по лицензии Creative Commons Attribution-NoDerivs 3.0.
Developed by digital.workshop

Источник

Как скопировать имя файла в терминале линукс?

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

Заранее благодарен за помощь.

Простой 2 комментария

я понимаю смысл pwd в буфер обмена быстро засовывать, немного.
Но зачем засовывать имя файла в буфер обмена, если вы все равно будете его печатать? Не проще сразу напечатать там где надо? Опишите кейс какой нибудь, пожалуйста

serii81

Евгений, мне нужно прописать имя файла в пути в коде, допустим наименование картинки.
Представьте что оно слишком длинное.

deepblack

alias pbcopy=’xclip -selection clipboard’

serii81

thiago_alvarez

Вы случайно не знаете как на линуксе скопировать всю папку целиком с ftp сервера?
ftp> mget копирует множество файлов не не директорию

как-то с wget можно было. не помню(

Читайте также:  Linux find регулярные выражения

serii81

Thiago Alvarez, нет, я еще до этого не дошел.
Я на сервере или на локалке архивирую папки, потом скачиваю

Gets selected files with expanded wildcards.

-c continue, reget.
-d create directories the same as file names and get the files into them instead of current directory.
-E delete source files after successful transfer
-e delete target file before the transfer
-a use ascii mode (binary is the default)
-P N download N files in parallel
-O specifies base directory or URL where files should be placed

Это из пакета lftp. Вроде как ftp уже устаревший давно считается. Но думаю, там аналогично будет.
Опция -d Вам нужна, вроде бы.

Войдите, чтобы написать ответ

Почему команда curl на windows не подключается к серверу?

Источник

Как получить полное имя файла в одну команду?

Как получить полное (с путём относительно / ) имя файла в одну команду? Бывает, работаешь в консоли, и нужно скопировать /полный/путь/к/файлу , например, чтобы в соседней консоли использовать его как аргумент для scp . Приходится вызывать pwd , чтобы скопировать путь к текущей папке, и ls , чтобы скопировать имя файла. Можно ли это сделать в одну команду?

Например, find ‘pwd’/имя_файла (кавычки вокруг pwd — обратные). Или ещё куча вариантов, например, с readlink , как указано в ответе ниже. Количество команд и/или аргументов при этом не имеет вообще никакого значения, ибо есть алиасы.

4 ответа 4

readlink -f покажет /полный/путь/к/файлу.ext , дополнительно «раскрыв» все символические ссылки и заменив их на «канонические» пути. Пример показателен:

$ cd /tmp $ mkdir foo $ touch foo/bar.ext $ ln -s foo/bar.ext baz.ext $ readlink -f foo/bar.ext /tmp/foo/bar.ext $ readlink -f baz.ext /tmp/foo/bar.ext 

Здесь /tmp/baz.ext является симлинком на /tmp/foo/bar.ext .

Предложенное решение работает в Linux и FreeBSD, но не работает в Mac OS — у них там своя атмосфера.

Предложу вариант чуть понавороченней:

readlink -m файл | tr -d '\r\n' | xsel -b 
  1. Читаем полный путь
  2. Сразу же копируем его в буфер обмена, предварительно .
  3. . вырезав конечные СR/LF (если не хотим, чтобы они добавлялись при вставке)

Для файлов относительно текущего каталога

можно, например, подставлять то, что содержится в переменной окружения $PWD (или в любой другой переменной окружения), даже без «команды», а всего лишь клавиатурным сочетанием. если, конечно, ваша оболочка использует gnu/readline для редактирования командной строки.

например, такая команда привяжет к клавиатурному сочетанию alt+o подстановку значения переменной $PWD (и слэша в конце — для удобства) в текущую позицию курсора:

здесь \eo — это и есть alt+o (а, например, \C-o — это ctrl+o ).

чтобы данная привязка создавалась автоматически в каждой сессии оболочки, можно добавить приведённую команду, например, в стартовый скрипт используемой оболочки — ~/.$rc .

а ещё лучше — добавить строку, которая в примере выше передавалась встроенной команде оболочки bind, прямо в файл ~/.inputrc (конф. файл, используемый gnu/readline-ом):

Источник

Оцените статью
Adblock
detector