Найти и переместить файлы на один уровень вверх

Вопрос или проблема

Я пытаюсь искать файлы с определенным расширением и затем перемещать их на один уровень выше в иерархии папок.

В принципе, у меня есть что-то вроде

/path/to/application/files/and/stuff/a1/nolongerneededirectory/*.*
/path/to/application/files/and/stuff/a2/nolongerneededirectory/*.*
/path/to/application/files/and/stuff/a3/nolongerneededirectory/*.*

Я пытаюсь переместить их вот так:

/path/to/application/files/and/stuff/a1/*.*
/path/to/application/files/and/stuff/a2/*.*
/path/to/application/files/and/stuff/a3/*.*

Идеально было бы сделать что-то вроде:

-bash-3.2$ find /path/to/ -name '*.txt'
output:
/path/to/directories1/test1/test1.txt
/path/to/directories2/test2/test2.txt
/path/to/directories3/test3/test3.txt

then 
mv /path/to/directories1/test1/test1.txt /path/to/directories1/test1.txt
mv /path/to/directories2/test2/test2.txt /path/to/directories2/test2.txt
mv /path/to/directories3/test3/test3.txt /path/to/directories3/test3.txt

Я пробовал разные варианты и спрашивал вокруг, есть у кого-нибудь идеи?

ИЗМЕНЕНИЕ 1:

Итак, я попробовал

`find /path/to/parent/dir -type f -exec mv {} .. \

но получаю Permission Denied

Если у вас есть GNU find, вы могли бы сделать (изменено из вашего примера):

find /path/to -type f -execdir mv {} .. \;

но в Solaris используется POSIX find как стандарт, который не имеет этой опции. Иногда доступны инструменты GNU (например, gfind).

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


Без GNU find, используя скрипт:

#!/bin/sh
IFS='
'
for i in $(find /path/to -type f); do
    echo mv -- "${i}" "${i%/*/*}"
done

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

Создайте скрипт под названием move_to_parent.sh, сделайте его исполняемым.

#!/bin/bash

while [ $# -ge 1 ]
do
   parentPath=${1%/*/*};
   cp "$1" $parentPath;
   shift
done

Информация о замене параметров.

Вот еще один способ написания move_to_parent.sh с использованием awk –

#!/bin/bash

while [ $# -ge 1 ]
do
   echo $1 | awk -F/ '
             {
                parentPath="";

                for(loop=2;loop<NF-1;loop++)
                {
                   parentPath=parentPath"https://superuser.com/"$loop;
                }
                sub(/\ /, "\ ", $0);
                system("mv " $0 " " parentPath );
             }'
   shift
done

Запустите следующим образом –

find /path/to/parent/dir -iname "*.txt" | xargs  /path/to/scripts/move_to_parent.sh

Однострочник, который похож на функцию, приведенную в предыдущих ответах, это:

for i in $(find /path/to/ -name "*file_extension"); do mv $i ${i%/*/*}; done

где file_extension следует заменить, например, на .txt.

.

Ответ или решение

Теория

В задачах компьютерной обработки файлов, одна из распространенных задач — это поиск и перемещение файлов в файловой системе. В данном случае требуется найти все файлы с определенным расширением в подкаталоге и переместить их на один уровень выше в файловой иерархии. Это может быть полезно для упрощения структуры каталогов или для подготовки данных перед использованием. Для этой задачи обычно используется командная оболочка Unix и утилиты командной строки, такие как find, mv и xargs.

Утилита find позволяет искать файлы в каталогах на основе различных критериев, таких как имя файла, тип файла и глубина вложенности. Команда mv используется для перемещения или переименования файлов, а xargs помогает в обработке выходных данных команды и передачи их в другие команды в нужной форме.

Пример

Рассмотрим конкретный пример использования средств командной строки для выполнения этой задачи. Допустим, наша начальная структура каталогов представлена следующим образом:

/path/to/application/files/and/stuff/a1/nolongerneededirectory/*.*
/path/to/application/files/and/stuff/a2/nolongerneededirectory/*.*
/path/to/application/files/and/stuff/a3/nolongerneededirectory/*.*

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

/path/to/application/files/and/stuff/a1/*.*
/path/to/application/files/and/stuff/a2/*.*
/path/to/application/files/and/stuff/a3/*.*

Применение

Существует несколько способов достижения этой цели. Рассмотрим несколько подходов.

1. Используем find и mv с -execdir:

find /path/to/application/files/and/stuff -type f -execdir mv {} .. \;

Этот метод подходит, если у вас есть доступ к GNU-версии find, которая поддерживает -execdir. Он перемещает каждый найденный файл на один уровень вверх.

2. Bash скрипт без -execdir:

Если GNU find недоступен, можно воспользоваться небольшим скриптом:

#!/bin/sh
IFS='
'
for i in $(find /path/to/application/files/and/stuff -type f); do
    echo mv -- "${i}" "${i%/*/*}"
done

Перед запуском скрипта, можно удалить echo, чтобы реальные перемещения произошли.

3. Использование скрипта на bash:

Вот пример скрипта move_to_parent.sh, который можно использовать для перемещения:

#!/bin/bash

while [ $# -ge 1 ]
do
   parentPath=${1%/*/*};
   mv "$1" $parentPath;
   shift
done

Этот скрипт принимает список файлов, разбирает путь и перемещает файлы на одну директорию вверх.

4. Однострочник с find и xargs:

Можно также использовать однострочник для аналогичной задачи:

find /path/to/ -name "*.txt" | xargs -I{} mv {} $(dirname {}/..)

Этот подход работает за счет использования xargs для обработки вывода find и перемещения файлов.

Заключение

Перемещение файлов на одну директорию вверх — это типичная задача административного управления, которую можно решить разными способами при помощи командной строки. Рекомендуется внимательно проверять структуру своих команд и сначала тестировать их с echo, чтобы избежать нежелательных изменений в файловой системе. Эти техники полезны не только для систематизации данных, но и для оптимизации работы с большими наборами файлов в автоматизированных задачах.

Оцените материал
Добавить комментарий

Капча загружается...