Esta no es una respuesta directa a la pregunta original, que pidió Why doesn't [..] work?
, pero esta respuesta puede ser útil para las personas que buscan un ̲ c ̲ h ̲ i ̲ e ̲ v ̲ e ̲ lo que sería el resultado lógico de algo como esto:
echo:somevalue|set /p somevar=
la solución normal, por ejemplo para el código anterior, sería la siguiente:
echo:somevalue>tempfile.txt&set /p somevar=<tempfile.txt
que hace el trabajo a la perfección, excepto que crea un nuevo archivo que debe tratarse posteriormente (además del hecho de que debemos tomar medidas adicionales para asegurarnos de que este nuevo archivo no sobrescriba uno existente) no creamos o nunca intentamos reemplazar).
Si bien es cierto que es ninguna manera alrededor de usar una secuencia de archivo para cerrar la brecha a través de ambos lados del operador tubería |
en lo que se refiere a las variables de entorno, estar bajo un entorno Windows NT y proporcionan el volumen del guión reside en que se utiliza el sistema de archivos NTFS, se puede usar algo mucho más elegante que los archivos temporales: salto alternate data streams
Vamos a la derecha en un ejemplo que ilustra cómo se podría usarlos:
echo:somevalue>".\%~nx0":temp&set /p somevar=<".\%~nx0":temp
Aquí %~nx0
significa, y se amplía a, el nombre de archivo (nombre base + extensión) de nuestro archivo de proceso por lotes, entre comillas en caso de que contenga espacios.
Nota: Si bien se podría utilizar %0
directamente (sin comillas) en lugar de referirse a el script actual, .\%~nx0
es más manejable si alguna vez tiene que mirada en el valor expandido de la orden durante la depuración su script, especialmente si la ruta completa de su script es bastante larga.
Como tal, ".\%~nx0":temp
se refiere a una secuencia de datos alternativa (ADS) de nuestro script propia llamado temp
, por ejemplo myscript.cmd:temp
, que creamos (o sobrescribir) con la salida del comando echo
. Como los ADS se comportan de la misma manera que la transmisión predeterminada de un archivo, los comandos echo
y set
no ven ninguna diferencia.
Un guión completo utilizando el método podría tener este aspecto:
@echo off
set __self=".\%~nx0"
set __adsname=test.dat
:: Using some input...
set [email protected],-23000
echo:Input: %l_input%
echo:
:: ...we process it...
expand_str_res_id.exe %l_input%>%__self%:%__adsname%&set /p l_output=< %__self%:%__adsname%
:: ...and show the output, e.g. "File and Printer Sharing"
echo:Output: %l_output%
echo:
:cleanup
set l_input=
set l_output=
type nul> %__self%:%__adsname%
set __self=
set __adsname=
pause
Aquí, al final de la secuencia de comandos, la línea type nul> %__self%:%__adsname
, que podría ampliarse a algo así como type nul> ".\myscript.cmd":test.dat
, se utiliza para borrar el contenido de la secuencia de datos alternativa que acabamos de utilizar. Aunque esto establece el tamaño de la secuencia de datos alternativa en cero, lo hace no borrarlo (ver notas a continuación).
Algunas notas finales:
mayoría de los comandos no pueden entender o trabajar con flujos de datos alternativos cuando se proporcionan como archivos de origen . Esto significa que no se pueden usar los siguientes:
type
, p. type myscript.cmd:data > myscript_data.txt
copy
, p. Ej. copy myscript.cmd:data myscript_data.txt
move
, p. Ej. move myscript.cmd:data myscript_data.txt
del
/erase
, p. del myscript.cmd:data
ren
/rename
, p. ren myscript.cmd:data myscript.cmd:data.txt
- y así sucesivamente
De hecho, es realmente sólo la redirección de archivos que soporta flujos de datos alternativos con una excepción (que se me ocurre): el comando start
.
- Aunque podemos con bastante facilidad claro/borrar el contenido de una secuencia de datos alternativa, eliminando uno es bastante complicado ya que la copia de un archivo o el cambio de nombre no implica ningún corrientes (así
:$DATA
unos), y la edición/cambio del el contenido de un archivo solo afecta la secuencia de datos predeterminada. Sin embargo, tenemos algunas opciones dependiendo de lo que estamos tratando de lograr:
- Si sólo tenemos un único flujo de datos alternativo o no les importa la eliminación de todas de ellos a la vez, y el contenido del archivo es solo texto, entonces podemos crear un nuevo archivo manteniendo solo la secuencia de datos predeterminada del archivo original usando el siguiente comando
type myscript.cmd > myscript_clean.cmd
, luego de lo cual se puede eliminar el archivo original.
- Si tenemos derechos administrativos en el volumen y funcionan bajo Windows Vista o una versión posterior del sistema operativo, podemos utilizar MKLINK para crear un enlace simbólico a uno secuencia de datos alternativa, que a su vez nos proporcionará una nombre de archivo estándar para ser utilizado con los comandos habituales de gestión de archivos.
- Alternativamente, uno puede usar una de las muchas herramientas disponibles para manipular flujos de datos alternativos, como Streams, LADS o AlternateStreamView.
- Un comando útil para listar los archivos normales incluyendo secuencias de datos alternativas desde la línea de comandos es
dir /a-d /r
. A continuación, puede usar cualquier programa para acceder a la secuencia de datos de nombre (alternativa) de un archivo, p. notepad.exe myscript.cmd:data
Espero que esto ayude!
Casualmente, necesitaba tomar un número del estándar de un programa, hacer algunos cálculos sobre él y luego canalizarlo a otro para el uso. Esto parece hacer el truco: echo 5 | (set/P TmpVar = && set/a TmpVar/2)> C: \ test.txt – TonyM
+1; De hecho, el problema es el resultado de cómo Windows implementa tuberías. Ver [¿Por qué falla la expansión retrasada cuando está dentro de un bloque de código procesado?] (Http://stackoverflow.com/q/8192318/1012053) para obtener una explicación completa del mecanismo, junto con muchos efectos secundarios interesantes. – dbenham