AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 406561
Accepted
A T
A T
Asked: 2017-11-24 04:41:42 +0800 CST2017-11-24 04:41:42 +0800 CST 2017-11-24 04:41:42 +0800 CST

GNU find: obtenha caminho absoluto e relativo em -exec

  • 772

Eu tenho um comando (não echo!) Que desejo executar, que usa um caminho absoluto e um caminho relativo.

Como obtenho esses dois argumentos?

Tentar:

d=/tmp/foo;
find "$d" -type f -exec bash -c 'echo d=${1:${#d}} 1="${1%/*}"' bash {} \;

(Eu gosto do GNU find porque é recursivo, pode restringir por arquivo, pode filtrar por nome de arquivo e não gera shells excessivos)

Expectativa:

mkdir -p /tmp/foo/bar/can/haz; touch /tmp/foo/bar/can/haz/bzr.txt
# cmd is run, output is:
d=bar/can/haz 1=/tmp/foo/bar/can/haz
bash find
  • 1 1 respostas
  • 2170 Views

1 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2017-11-24T05:33:39+08:002017-11-24T05:33:39+08:00

    Export d, ele estará disponível em seu bashscript embutido. Você também não precisa bashde nada aqui. O seu (esperançosamente mais magro/rápido) shtambém funcionaria. Além disso, você não precisa executar um shell por arquivo. Você pode passar mais arquivos para seu script embutido com a -exec cmd {} +variante:

    d=/tmp/foo
    export d
    find "$d" -type f -exec sh -c '
      for file do
        relative=${file#"$d/"}
        dir=${file%/*}
        relative_dir=${relative%/*}
        relative_dir=${relative_dir:-.}
        printf "%10s: %s\n" full "$file" \
                            relative "$relative" \
                            dir "$dir" \
                            reldir "$relative_dir"
      done' sh {} +
    

    Que dá:

          full: /tmp/foo/bar/can/haz/bzr.txt
      relative: bar/can/haz/bzr.txt
           dir: /tmp/foo/bar/can/haz
        reldir: bar/can/haz
    

    Mas se você precisar apenas do caminho relativo, pode ser mais simples fazer apenas:

    (cd -P -- "$d" && find . -exec sh -c 'for file do...' sh {} +)
    

    Isso também tornaria os argumentos de comando passados ​​para shmais curtos, permitindo findpassar mais argumentos para sh.

    Observe que não há nada específico do GNU em seu findcomando nem no meu. Isso deve funcionar em qualquer implementação compatível com POSIX find, não apenas na GNU. A única parte não-POSIX em sua pergunta foi obviamente bashe o ${1:offset}operador que é um operador de shell Korn, não em POSIX sh.

    Para uma pesquisa de arquivo recursiva que permite especificar o tipo de arquivo, consulte também zsh:

    (cd -P -- "$d" &&
      for file (**/*(ND.)) {
        dir=$file:h
        printf '%10s: %s\n' relative $file reldir $dir
      })
    

    Acima, o .é o equivalente a find's -type f(somente arquivos regulares), enquanto Dtambém inclui os ocultos como finddoes.


    Como nota lateral, no caso geral:

    c=$a$b; d=${c:${#a}}
    [ "$b" = "$d" ] && echo yes
    

    Não é garantido que a saída seja "sim", porque os operadores ${#var}e trabalham com caracteres , não com bytes .${var:offset}

    Por exemplo, em uma localidade UTF-8, não resultaria sim com esses valores de ae b:

    a=$'St\xc3' b=$'\xa9phane'
    

    Com esses, $cconteria meu primeiro nome ( Stéphane) conteria $ametade desse écaractere e $ba outra metade, ${#a}seria 3(2 caracteres e 1 byte não formando um caractere válido, mas ainda contado).

    Assim $dseria phane, não $'\xa9phane'.

    No caso específico de d=$a/$b, porém, deve estar OK, pois nenhum dos conjuntos de caracteres geralmente disponíveis em localidades do sistema teria um caractere diferente /daquele que contém a codificação de /.

    • 5

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve