Вопрос или проблема
Я пытаюсь искать файлы с определенным расширением и затем перемещать их на один уровень выше в иерархии папок.
В принципе, у меня есть что-то вроде
/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
, чтобы избежать нежелательных изменений в файловой системе. Эти техники полезны не только для систематизации данных, но и для оптимизации работы с большими наборами файлов в автоматизированных задачах.