A ordem de processamento e impressão de arquivos com find

2

Este simples script BASH coleta msgstrs em um projeto PHP:

#!/bin/sh
TARGET=/path/to/project
LPATH=locale/cy_GB/LC_MESSAGES
POFILE=messages.po
mkdir -p $LPATH
touch $TARGET/$LPATH/$POFILE
cd $TARGET
find . -name '*.php' -print | xargs xgettext -j --from-code=UTF-8 -o $TARGET/$LPATH/$POFILE

Eu tenho 2 perguntas:

  1. Por que não -print lista os arquivos que encontrou - todos os documentos dizem que deveria?

  2. Existe alguma maneira de especificar a ordem na qual encontrar transações com os arquivos? Se eu executar um script PHP equivalente, ele lida com os arquivos na ordem em que eles são listados por ls e, em seguida, entra no diretório dirs. Mas achado parece fazer sua própria coisa, com os arquivos desordenados em nenhuma ordem aparente, e os dirs intercalados com eles?

por donnek 16.12.2013 / 11:46

3 respostas

4

find não tem nada a ver com o bash, é um utilitário separado, provavelmente fornecido em seu sistema pelo GNU findutils, se você estiver executando o Linux.

-print lista os arquivos, mas você não precisa deles - é o padrão. A razão pela qual você provavelmente não os "vê" é porque sua saída está sendo obtida por xargs no stdin - ele nunca chega ao seu terminal. Se você quer ir para ambos, você precisa usar tee ou similar (note que se você está recebendo nomes de arquivos não confiáveis, você deve sempre usar -print0 , o que não está incluído aqui porque é uma extensão não portável):

find . -name '*.php' |
    tee >(xargs xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE")

find imprimirá os arquivos na ordem em que os encontrar, o que não está classificado. Se você quer que eles estejam em ordem, você precisa executar sort primeiro.

    
por 16.12.2013 / 11:58
1

find . -name '*.php' -print imprime a lista de nomes de arquivos. É aí que xargs recebe sua entrada.

Para evitar surpresas desagradáveis com nomes de arquivos contendo espaço em branco e outros caracteres especiais, use -print0 e xargs -0

find . -name '*.php' -print0 | xargs -0 xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE"

ou use a ação -exec :

find . -name '*.php' -exec xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE" {} +

Tenha em atenção que, se existirem muitos ficheiros, xgettext será executado várias vezes, uma vez por lote de ficheiros. Isso acontece se você usou xargs ou -exec . Para evitar isso, já que você está usando o bash, use o recurso de passagem de diretório recursivo integrado em vez de find .

shopt -s globstar
xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE" **/*.php

Dessa forma, se os nomes de arquivos concatenados passarem pelo limite de comprimento da linha de comando, você receberá um erro em vez de um arquivo silenciosamente truncado. Cuidado com o bash, **/ atravessa links simbólicos para diretórios, não apenas diretórios. Se isso for um problema, use ksh ou zsh em vez de bash ou use um método diferente.

Com find , para evitar a substituição silenciosa do arquivo de saída repetidamente, grave na saída padrão e redirecione todo o comando find para um arquivo.

find . -name '*.php' -exec xgettext -j --from-code=UTF-8 {} + >"$TARGET/$LPATH/$POFILE"

find lista os arquivos na ordem em que os encontra, não faz nenhuma classificação. Nem classificação por nome nem classificação de diretórios antes ou depois de outros arquivos. (Diretórios são arquivos. Não há uma lista separada de subdiretórios e de outros arquivos em um diretório.)

find sempre lista o conteúdo de um diretório imediatamente após o próprio diretório. Com a opção -depth , isso é revertido: primeiro o conteúdo de um diretório, depois o próprio diretório.

    
por 17.12.2013 / 03:05
0

Se o seu diretório de destino não tiver nenhuma subpasta, você pode tentar usar * para expandir todos os arquivos que terminam em .php e iterá-los com xgettext . Isso eliminaria a necessidade de find e xargs .

for i in ./*.php; do
    xgettext -j --from-code=UTF-8 -o $TARGET/$LPATH/$POFILE $i
done

Se você precisar fazer uma pesquisa recursiva com find , poderá iterar sobre a saída de um subconjunto contendo seu comando find .

for i in $(find . -name '*.php'); do
    xgettext -j --from-code=UTF-8 -o $TARGET/$LPATH/$POFILE $i
done
    
por 16.12.2013 / 19:17