Могу ли я также переместить или скопировать иерархию каталогов файла, когда я его mv
восстанавливаю ?cp
Например, если я mv
или cp
dir1/dir2/file
в другом месте, то это будет только mv
или cp
file
. А если я хочу также mv
или cp
dir1/dir2
? Вместо mkdir -p dir1/dir2
, можно ли это сделать одной командой?
решение1
Вы можете использовать cp
переключатель --parents
:
$ mkdir -p step1/step2/step3
$ touch step1/step2/step3/file
$ mkdir copy
$ cp --parents step1/step2/step3/file copy
$ ls copy/step1/step2/step3/file
copy/step1/step2/step3/file
mv
, однако, не имеет --parents
переключателя, но вы можете сделать что-то вроде:
$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete
Который будет:
- Найдите файл.
- Скопируйте его (вместе с его родителями) в место назначения.
- Удалить оригинал.
Для этого можно создать функцию:
mvparents()
{
[[ $# -ne 2 ]] && echo "2 arguments needed." && return
[[ ! -r "$1" ]] && echo "$1 is not readable." && return
[[ ! -d "$2" ]] && mkdir -p "$2"
find $(dirname $1) -name "$(basename $1)" -exec cp --parents {} $2/ \; -delete
}
$ mvparents step1/step2/step3/file copy/
Это может потребовать некоторых корректировок, если вы попытаетесь переместить несколько файлов. Вот пример (работает в bash, но нет гарантий для других оболочек):
mvparents()
{
[[ $# -lt 2 ]] && echo "Usage: $0 [source] <source> ... [destination]." && return
# Get the destination directory.
for dest; do true; done
[[ ! -d "$dest" ]] && mkdir -p "$dest"
# Copy the arguments and remove the destination.
parameters=( "$@" )
unset parameters[${#parameters[@]}-1]
# For each source file: find, copy, delete.
for source in "${parameters[@]}"; do
if [ -r "$source" ]; then
find $(dirname $source) -name "$(basename $source)" -exec cp --parents {} $dest/ \; -delete
else
echo "$0: $source is not readable."
fi
done
}
Ну... это немного дольше, чем я ожидал, но должно сработать.
Редактировать: какСебастьян Пихв комментарии указано, что полагаться на работу cp
do mv
- это сильно снижает производительность, так как mv
изначально не нужнокопияфайл, просто отредактируйте его метаданные. Вы можете заменить цикл выше на:
for source in "${parameters[@]}"; do
if [ -r "$source" ]; then
[[ ! -d "$dest/$(dirname $source)" ]] && mkdir -p "$dest/$(dirname $source)"
find $(dirname $source) -name "$(basename $source)" -exec mv {} "$dest/$(dirname $source)" \; -delete
else
echo "$0: $source is not readable."
fi
done
Однако, поскольку эта вещь опирается намногоЧто касается значения $PWD
, я бы попросил вас быть очень осторожными, если вы его используете.