Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

480
Visualizações
Get grandparent directory in bash script - rename files for a directory in their paths

I have the following script, which I normally use when I get a bunch of files that need to be renamed to the directory name which contains them.

The problem now is I need to rename the file to the directory two levels up. How can I get the grandparent directory to make this work?

With the following I get errors like this example: "mv: cannot move ./48711/zoom/zoom.jpg to ./48711/zoom/./48711/zoom.jpg: No such file or directory". This is running on CentOS 5.6.

I want the final file to be named: 48711.jpg

#!/bin/bash

function dirnametofilename() {
  for f in $*; do
    bn=$(basename "$f")
    ext="${bn##*.}"
    filepath=$(dirname "$f")
    dirname=$(basename "$filepath")
    mv "$f" "$filepath/$dirname.$ext"
  done
}

export -f dirnametofilename

find . -name "*.jpg" -exec bash -c 'dirnametofilename "{}"'  \;

find .
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Another method could be to use

(cd ../../; pwd)

If this were executed in any top-level paths such as /, /usr/, or /usr/share/, you would get a valid directory of /, but when you get one level deeper, you would start seeing results: /usr/share/man/ would return /usr, /my/super/deep/path/is/awesome/ would return /my/super/deep/path, and so on.

You could store this in a variable as well:

GRANDDADDY="$(cd ../../; pwd)"

and then use it for the rest of your script.

over 4 years ago · Santiago Trujillo Relatório

0

Assuming filepath doesn't end in /, which it shouldn't if you use dirname, you can do

Parent = "${filepath%/*}"
Grandparent = "${filepath%/*/*}"

So do something like this

[[ "${filepath%/*/*}" == "" ]] && echo "Path isn't long enough" || echo "${filepath%/*/*}"

Also this likely won't work if you're using relative paths (like find .). In which case you will want to use

filepath=$(dirname "$f")
filepath=$(readlink -f "$filepath")

instead of

filepath=$(dirname "$f")

Also you're never stripping the extension, so there is no reason to get it from the file and then append it again.

over 4 years ago · Santiago Trujillo Relatório

0

Note:
* This answer solves the OP's specific problem, in whose context "grandparent directory" means: the parent directory of the directory containing a file (it is the grandparent path from the file's perspective).
* By contrast, given the question's generic title, other answers here focus (only) on getting a directory's grandparent directory; the succinct answer to the generic question is: grandParentDir=$(cd ../..; printf %s "$PWD") to get the full path, and grandParentDirName=$(cd ../..; basename -- "$PWD") to get the dir. name only.

Try the following:

find . -name '*.jpg' \
  -execdir bash -c \
   'old="$1"; new="$(cd ..; basename -- "$PWD").${old##*.}"; echo mv "$old" "$new"' - {} \;

Note: echo was prepended to mv to be safe - remove it to perform the actual renaming.

  • -execdir ..\; executes the specified command in the specific directory that contains a given matching file and expands {} to the filename of each.

  • bash -c is used to execute a small ad-hoc script:

    • $(cd ..; basename -- "$PWD") determines the parent directory name of the directory containing the file, which is the grandparent path from the file's perspective.

    • ${old##*.} is a Bash parameter expansion that returns the input filename's suffix (extension).

    • Note how {} - the filename at hand - is passed as the 2nd argument to the command in order to bind to $1, because bash -c uses the 1st one to set $0 (which is set to dummy value _ here).

  • Note that each file is merely renamed, i.e., it stays in its original directory.

Caveat:

  • Each directory with a matching file should only contain 1 matching file, otherwise multiple files will be renamed to the same target name in sequence - effectively, only the last file renamed will survive.
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda