Я хочу переименовать имя файла с именем его родительской папки, добавив имя папки перед текущим именем.
Например:
Структура папок
SOCH NC KT 633-ROYAL BLUE-MULTI
|
| 1.jpg
|
| 2.jpg
|
| 3.jpg
Ожидаемый результат
SOCH NC KT 633-ROYAL BLUE-MULTI
|
|_SOCH NC KT 633-ROYAL BLUE-MULTI1.jpg
|
|_SOCH NC KT 633-ROYAL BLUE-MULTI2.jpg
|
|_SOCH NC KT 633-ROYAL BLUE-MULTI3.jpg
SOCH NC KT 710-BLACK-MULTI
Кто-нибудь может посоветовать, как это можно сделать в файле .sh? Есть ли какая-либо утилита для выполнения операции?
В маленьком сценарии Python, переименовывая файлы рекурсивно (папки, а также sub папки):
#!/usr/bin/env python3
import shutil
import os
import sys
dr = sys.argv[1]
for root, dirs, files in os.walk(dr):
for f in files:
shutil.move(root+"/"+f, root+"/"+root.split("/")[-1]+f)
rename_files.py
Выполните его с каталогом как аргумент:
python3 /path/to/rename_files.py /directory/with/files
Как всегда, сначала примерьте образец!
Сценарий:
Если файлы найдены, это разделяет путь к файлу с разделителем "/", сохраняя последнее в строке (который является именем папки родителя), чтобы быть вставленным перед именем файла:
root.split("/")[-1]
Впоследствии, переместите файл в переименованный:
shutil.move(root+"/"+f, root+"/"+root.split("/")[-1]+f)
Вот небольшой пример того, как это может быть сделано, формируют каталог, который Вы хотите отредактировать.
$> ls
file1.txt file2.txt file3.txt
$> pwd
/home/xieerqi/testing_dir
$> find . -type f -printf "%f\0" | \
> while IFS="" read -d "" filename ; do \
> echo $filename ${PWD##*/}_$filename ; done
file2.txt testing_dir_file2.txt
file1.txt testing_dir_file1.txt
file3.txt testing_dir_file3.txt
Замена echo
с mv
или cp
для копирования или перемещения по мере необходимости
Решение для Bash, выполняющееся от папки, где имена файлов Вы хотите измениться, помещается. Необходимо измениться workdir
на путь
#!/bin/bash
shopt -s globstar
workdir="/path/to/your/dir"
for folder in $workdir/**/*;do
if [[ -d "$folder" ]]; then
for file in "$folder"/*;do
if [[ -f "$file" ]]; then
fi="`basename "$file"`"
fo="`basename "$folder"`"
mv "$file" "$folder/$fo$fi"
fi
done
fi
done
, Он изменится все файлы в все каталоги рекурсивно от workdir.
Используя только окружают (bash
) с небольшой справкой от mv
:
#!/bin/bash
shopt -s globstar ##globstar will let us match files recursively
files=( /foo/bar/**/*.jpg ) ##Array containing matched files, mention where to search and what files here
for i in "${files[@]}"; do
d="${i%/*}" ##Parameter expansion, gets the path upto the parent directory
d_="${d##*/}" ##gets the name of parent directory
f="${i##*/}" ##gets the file name
echo mv "$i" "$d"/"${d_}""$f" ##renaming, remove echo after confirming what will be changed and you are good
done
Пример:
$ shopt -s globstar
$ files=( /foo/bar/**/*.jpg )
$ for i in "${files[@]}"; do d="${i%/*}"; d_="${d##*/}"; f="${i##*/}"; echo mv "$i" "$d"/"${d_}""$f"; done
mv /foo/bar/KT/633-ROYAL/4.jpg /foo/bar/KT/633-ROYAL/633-ROYAL4.jpg
mv /foo/bar/KT/633-ROYAL/5.jpg /foo/bar/KT/633-ROYAL/633-ROYAL5.jpg
mv /foo/bar/KT/633-ROYAL/6.jpg /foo/bar/KT/633-ROYAL/633-ROYAL6.jpg
mv /foo/bar/KT/633-ROYAL/BLUE-MULTI/1.jpg /foo/bar/KT/633-ROYAL/BLUE-MULTI/BLUE-MULTI1.jpg
mv /foo/bar/KT/633-ROYAL/BLUE-MULTI/2.jpg /foo/bar/KT/633-ROYAL/BLUE-MULTI/BLUE-MULTI2.jpg
mv /foo/bar/KT/633-ROYAL/BLUE-MULTI/3.jpg /foo/bar/KT/633-ROYAL/BLUE-MULTI/BLUE-MULTI3.jpg
Можно сделать это с rename
:
rename -n 's/(.*)\//$1\/$1/' */*
Эта команда должна быть запущена в каталоге непосредственно выше каталогов, которые Вы хотите обработать. Это сначала только перечислит изменения для Вас для проверки, если Вы будете довольны результатами, выполненными это без -n
выполнить переименование.
$ tree
.
└── SOCH NC KT 633-ROYAL BLUE-MULTI
├── 1.jpg
├── 2.jpg
└── 3.jpg
$ rename 's/(.*)\//$1\/$1/' */*
$ tree
.
└── SOCH NC KT 633-ROYAL BLUE-MULTI
├── SOCH NC KT 633-ROYAL BLUE-MULTI1.jpg
├── SOCH NC KT 633-ROYAL BLUE-MULTI2.jpg
└── SOCH NC KT 633-ROYAL BLUE-MULTI3.jpg
rename 's/(.*)\//$1\/$1/' */*
s/a/b/
– s
замена a
b
(.*)\/
– возьмите все до (excl). последняя наклонная черта, сохраняющая его как группа 1 и замена он$1\/$1
– группа 1 (имя dir), наклонная черта и группа 1 снова (префикс имени файла)Еще один подход только для удара, чтобы быть выполненным в папке, где файлы, которым нужно переименование, находятся:
for f in * ; do mv "$f" "$(basename "$(pwd)")"_"$f" ; done
Это также обработает имена файлов и имена папок с пробелами.