How to Strip Path Prefixes from find Command Output for Deployment Scripts


2 views

When automating file deployments using find commands, we often encounter path prefixes that interfere with our copy operations. Consider this common scenario:

find . -type f -mtime -14 > deploy.txt
# Output contains './path/to/file.ext' 
# But we need just 'path/to/file.ext'

Here are three effective approaches to remove the leading ./:

1. Using parameter expansion in a loop

find . -type f -mtime -14 | while read -r file; do
  echo "${file#./}" >> deploy.txt
done

2. Leveraging sed for direct stream editing

find . -type f -mtime -14 | sed 's|^\./||' > deploy.txt

3. Using printf formatting with find -print0

find . -type f -mtime -14 -printf '%P\\n' > deploy.txt

Here's how I integrated this into my production deployment workflow:

#!/bin/bash

# Generate clean file list
find . -type f -mtime -14 -printf '%P\\n' > /tmp/deploy.txt

# Deployment loop
BETA_DIR="/home/user/beta/public_html"
PROD_DIR="/home/user/public_html"

while read -r file; do
  if [[ -f "$BETA_DIR/$file" ]]; then
    cp -i "$BETA_DIR/$file" "$PROD_DIR/$file"
    echo "Deployed: $file"
  else
    echo "Warning: $file not found in beta" >&2
  fi
done < /tmp/deploy.txt

# Clean up
rm /tmp/deploy.txt

For more robust handling, consider these improvements:

# Skip directories accidentally captured
find . -type f -mtime -14 ! -path "./.*" -printf '%P\\n'

# Exclude specific directories
find . -type f -mtime -14 ! -path "./node_modules/*" -printf '%P\\n'

For large codebases, these optimizations help:

# Use parallel processing with xargs
find . -type f -mtime -14 -print0 | sed -z 's|^\./||' | xargs -0 -P4 -I{} cp -i "$BETA_DIR/{}" "$PROD_DIR/{}"

When automating file deployments between environments, we often need to process find command output that includes relative paths (./ prefix). Here's how to clean this up for reliable script execution.

For processing find output, we have several effective approaches:

# Using basename in a while loop
find . -type f -mtime -14 | while read -r file; do
  echo "$(basename "$file")"
done > deploy.txt

# Using parameter expansion (faster)
find . -type f -mtime -14 | while read -r file; do
  echo "${file##*/}"
done > deploy.txt

Here's a robust implementation that handles filenames with spaces and special characters:

#!/bin/bash
# Generate clean file list
find . -type f -mtime -14 -print0 | while IFS= read -r -d '' file; do
  echo "${file#*/}"
done > deploy.txt

# Deployment loop
while IFS= read -r -d '' file; do
  cp -iv "/home/user/beta/public_html/${file}" "/home/user/public_html/${file}"
done < <(find . -type f -mtime -14 -print0 | sed 's|^\./||')

For complex deployments, consider these enhancements:

# Exclude certain directories
find . -type f -mtime -14 ! -path "./cache/*" ! -path "./tmp/*" | sed 's|^\./||'

# Add timestamp logging
find . -type f -mtime -14 -printf "%TY-%Tm-%Td %TH:%TM %p\n" | awk '{sub(/^\.\//, ""); print}'

For better performance with large file sets:

find . -type f -mtime -14 -print0 | sed -z 's|^\./||' | xargs -0 -I {} cp -iv \
  "/home/user/beta/public_html/{}" "/home/user/public_html/{}"