Скопируйте файлы из нескольких каталогов, если их имя появляется в списке, в один каталог.

Вы можете поместить в каталог /etc/profile.d/ что-то вроде следующего в виде скрипта:

#!/bin/bash
    if [ $SHLVL = 1 ]; then
    echo -n "Enter proxy password:"
    read -sr mypass
    export http_proxy="http://$USER:$mypass@proxy.example.com:6080"
    export https_proxy=$http_proxy
    echo
fi

if [ $SHLVL = 1 ]предотвратит запуск сценария при создании подоболочек, например, при запуске сценария для ведения журнала.

read -sпредотвратит эхо ввода при вводе пароля.

$USER— это переменная среды, которая является текущим именем пользователя.

Окончательный echoпросто печатает новую строку, чтобы получить следующее приглашение на следующей строке.

0
14.04.2020, 18:16
2 ответа

Выполняется findодин раз для каждого имени файла и предполагается, что ни одно имя файла не содержит встроенных символов новой строки:

#!/bin/sh

mkdir -p destination_folder || exit 1
while IFS= read -r name; do
    find. -path./destination_folder -prune -o \
        -type f -name "$name" -exec cp {} destination_folder \;
done <spreadsheet.txt

Сначала создается целевой каталог в текущем каталоге (и завершается, если это не удается ). Затем он считывает входной файл, строка за строкой, и вызывает find, чтобы найти любой обычный файл с таким именем. Каталог назначения явно избегается с помощью findс использованием -pruneвсякий раз, когда мы сталкиваемся с ним в нашем поиске.

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

Если текущий каталог огромен, или если список имен файлов длинный (, но не много тысяч строк ), то это будет медленная операция. Поэтому мы можем сделать одиночный вызов find. Следующий код предполагает, что он выполняется, например. bashпоскольку он использует массивы:

#!/bin/bash

mkdir -p destination_folder || exit 1

names=()
while IFS= read -r name; do
    names+=( -o -name "$name" )
done <spreadsheet.txt

find. -path./destination_folder -prune -o \
    \( "${names[@]:1}" \) -type f -exec cp -t destination_folder {} +

Здесь я также решил использоватьcp -t(расширение GNU cp), чтобы иметь возможность вызывать cpкак можно меньше раз, а не один раз для каждого найденного файла.

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

find. -path./destination_folder -prune -o '(' -name AB.txt -o -name CD.txt -o -name EF.txt ')' -type f -exec cp -t destination_folder '{}' +

Чтобы избежать конфликта имен файлов в целевом каталоге, если вы используете GNU cp(, например. в системе Linux ),использовать cpс его опцией -bили --backup.

В системах, отличных от -Linux, GNU cpчасто может быть доступен как gcpпосле установки GNU coreutils через диспетчер пакетов.


Тот же последний скрипт, но для/bin/sh(нет массивов):

#!/bin/sh

mkdir -p destination_folder || exit 1

set --
while IFS= read -r name; do
    set -- -o -name "$name" "$@"
done <spreadsheet.txt

shift

find. -path./destination_folder -prune -o \
    \( "$@" \) -type f -exec cp -t destination_folder {} +
0
19.03.2021, 02:29

Простой цикл for:

for filename in $(cat spreadsheet.txt)
do
find. -name "$filename" -exec cp {} /destination/folder \;
done
0
19.03.2021, 02:29

Теги

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